blob: 5c96d91726bbfd3a9e31698416e1535edb31950f [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 Langf41a7152016-09-19 15:11:17 -0400929} // anonymous namespace
930
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500931bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400932{
Jamie Madilld7460c72014-01-21 16:38:14 -0500933 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400934 {
Jamie Madilld7460c72014-01-21 16:38:14 -0500935 case GL_TEXTURE_2D:
936 case GL_TEXTURE_CUBE_MAP:
937 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400938
Jamie Madilld7460c72014-01-21 16:38:14 -0500939 case GL_TEXTURE_3D:
940 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300941 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500942
943 default:
944 return false;
945 }
Jamie Madill35d15012013-10-07 10:46:37 -0400946}
947
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500948bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
949{
950 switch (target)
951 {
952 case GL_TEXTURE_2D:
953 case GL_TEXTURE_CUBE_MAP:
954 return true;
955
956 default:
957 return false;
958 }
959}
960
961bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
962{
963 switch (target)
964 {
965 case GL_TEXTURE_3D:
966 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300967 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500968
969 default:
970 return false;
971 }
972}
973
Ian Ewellbda75592016-04-18 17:25:54 -0400974// Most texture GL calls are not compatible with external textures, so we have a separate validation
975// function for use in the GL calls that do
976bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
977{
978 return (target == GL_TEXTURE_EXTERNAL_OES) &&
979 (context->getExtensions().eglImageExternal ||
980 context->getExtensions().eglStreamConsumerExternal);
981}
982
Shannon Woods4dfed832014-03-17 20:03:39 -0400983// This function differs from ValidTextureTarget in that the target must be
984// usable as the destination of a 2D operation-- so a cube face is valid, but
985// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400986// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500987bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400988{
989 switch (target)
990 {
991 case GL_TEXTURE_2D:
992 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
993 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
994 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
995 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
996 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
997 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
998 return true;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500999 default:
1000 return false;
1001 }
1002}
1003
1004bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1005{
1006 switch (target)
1007 {
Shannon Woods4dfed832014-03-17 20:03:39 -04001008 case GL_TEXTURE_3D:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001009 case GL_TEXTURE_2D_ARRAY:
1010 return true;
Shannon Woods4dfed832014-03-17 20:03:39 -04001011 default:
1012 return false;
1013 }
1014}
1015
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001016bool ValidFramebufferTarget(GLenum target)
1017{
Geoff Langd4475812015-03-18 10:53:05 -04001018 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
1019 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001020
1021 switch (target)
1022 {
1023 case GL_FRAMEBUFFER: return true;
1024 case GL_READ_FRAMEBUFFER: return true;
1025 case GL_DRAW_FRAMEBUFFER: return true;
1026 default: return false;
1027 }
1028}
1029
Jamie Madill29639852016-09-02 15:00:09 -04001030bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001031{
1032 switch (target)
1033 {
1034 case GL_ARRAY_BUFFER:
1035 case GL_ELEMENT_ARRAY_BUFFER:
1036 return true;
1037
Jamie Madill8c96d582014-03-05 15:01:23 -05001038 case GL_PIXEL_PACK_BUFFER:
1039 case GL_PIXEL_UNPACK_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001040 return (context->getExtensions().pixelBufferObject ||
1041 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001042
Shannon Woodsb3801742014-03-27 14:59:19 -04001043 case GL_COPY_READ_BUFFER:
1044 case GL_COPY_WRITE_BUFFER:
Jamie Madill8c96d582014-03-05 15:01:23 -05001045 case GL_TRANSFORM_FEEDBACK_BUFFER:
1046 case GL_UNIFORM_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001047 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001048
1049 default:
1050 return false;
1051 }
1052}
1053
Geoff Langff5b2d52016-09-07 11:32:23 -04001054bool ValidBufferParameter(const ValidationContext *context, GLenum pname, GLsizei *numParams)
Jamie Madill70656a62014-03-05 15:01:26 -05001055{
Geoff Langff5b2d52016-09-07 11:32:23 -04001056 // All buffer parameter queries return one value.
1057 *numParams = 1;
1058
Geoff Langcc6f55d2015-03-20 13:01:02 -04001059 const Extensions &extensions = context->getExtensions();
1060
Jamie Madill70656a62014-03-05 15:01:26 -05001061 switch (pname)
1062 {
1063 case GL_BUFFER_USAGE:
1064 case GL_BUFFER_SIZE:
1065 return true;
1066
Geoff Langcc6f55d2015-03-20 13:01:02 -04001067 case GL_BUFFER_ACCESS_OES:
1068 return extensions.mapBuffer;
1069
1070 case GL_BUFFER_MAPPED:
1071 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
Martin Radev1be913c2016-07-11 17:59:16 +03001072 return (context->getClientMajorVersion() >= 3) || extensions.mapBuffer ||
1073 extensions.mapBufferRange;
Geoff Langcc6f55d2015-03-20 13:01:02 -04001074
Jamie Madill70656a62014-03-05 15:01:26 -05001075 // GL_BUFFER_MAP_POINTER is a special case, and may only be
1076 // queried with GetBufferPointerv
1077 case GL_BUFFER_ACCESS_FLAGS:
Jamie Madill70656a62014-03-05 15:01:26 -05001078 case GL_BUFFER_MAP_OFFSET:
1079 case GL_BUFFER_MAP_LENGTH:
Martin Radev1be913c2016-07-11 17:59:16 +03001080 return (context->getClientMajorVersion() >= 3) || extensions.mapBufferRange;
Jamie Madill70656a62014-03-05 15:01:26 -05001081
1082 default:
1083 return false;
1084 }
1085}
1086
Jamie Madillc29968b2016-01-20 11:17:23 -05001087bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001088{
Jamie Madillc29968b2016-01-20 11:17:23 -05001089 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001090 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001091 switch (target)
1092 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001093 case GL_TEXTURE_2D:
1094 maxDimension = caps.max2DTextureSize;
1095 break;
Geoff Langce635692013-09-24 13:56:32 -04001096 case GL_TEXTURE_CUBE_MAP:
1097 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1098 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1099 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1100 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1101 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
Jamie Madillc29968b2016-01-20 11:17:23 -05001102 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1103 maxDimension = caps.maxCubeMapTextureSize;
1104 break;
1105 case GL_TEXTURE_3D:
1106 maxDimension = caps.max3DTextureSize;
1107 break;
1108 case GL_TEXTURE_2D_ARRAY:
1109 maxDimension = caps.max2DTextureSize;
1110 break;
Geoff Langce635692013-09-24 13:56:32 -04001111 default: UNREACHABLE();
1112 }
1113
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001114 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001115}
1116
Austin Kinross08528e12015-10-07 16:24:40 -07001117bool ValidImageSizeParameters(const Context *context,
1118 GLenum target,
1119 GLint level,
1120 GLsizei width,
1121 GLsizei height,
1122 GLsizei depth,
1123 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001124{
1125 if (level < 0 || width < 0 || height < 0 || depth < 0)
1126 {
1127 return false;
1128 }
1129
Austin Kinross08528e12015-10-07 16:24:40 -07001130 // TexSubImage parameters can be NPOT without textureNPOT extension,
1131 // as long as the destination texture is POT.
1132 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001133 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001134 {
1135 return false;
1136 }
1137
1138 if (!ValidMipLevel(context, target, level))
1139 {
1140 return false;
1141 }
1142
1143 return true;
1144}
1145
Geoff Lang0d8b7242015-09-09 14:56:53 -04001146bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1147{
1148 // List of compressed format that require that the texture size is smaller than or a multiple of
1149 // the compressed block size.
1150 switch (internalFormat)
1151 {
1152 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1153 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1154 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1155 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001156 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001157 return true;
1158
1159 default:
1160 return false;
1161 }
1162}
1163
Jamie Madillc29968b2016-01-20 11:17:23 -05001164bool ValidCompressedImageSize(const ValidationContext *context,
1165 GLenum internalFormat,
1166 GLsizei width,
1167 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001168{
Geoff Lang5d601382014-07-22 15:14:06 -04001169 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1170 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001171 {
1172 return false;
1173 }
1174
Geoff Lang0d8b7242015-09-09 14:56:53 -04001175 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001176 {
1177 return false;
1178 }
1179
Geoff Lang0d8b7242015-09-09 14:56:53 -04001180 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1181 {
1182 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1183 width % formatInfo.compressedBlockWidth != 0) ||
1184 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1185 height % formatInfo.compressedBlockHeight != 0))
1186 {
1187 return false;
1188 }
1189 }
1190
Geoff Langd4f180b2013-09-24 13:57:44 -04001191 return true;
1192}
1193
Geoff Langff5b2d52016-09-07 11:32:23 -04001194bool ValidImageDataSize(ValidationContext *context,
1195 GLenum textureTarget,
1196 GLsizei width,
1197 GLsizei height,
1198 GLsizei depth,
1199 GLenum internalFormat,
1200 GLenum type,
1201 const GLvoid *pixels,
1202 GLsizei imageSize)
1203{
1204 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1205 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1206 {
1207 // Checks are not required
1208 return true;
1209 }
1210
1211 // ...the data would be unpacked from the buffer object such that the memory reads required
1212 // would exceed the data store size.
1213 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1214 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1215 const gl::Extents size(width, height, depth);
1216 const auto &unpack = context->getGLState().getUnpackState();
1217
1218 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1219 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1220 if (endByteOrErr.isError())
1221 {
1222 context->handleError(endByteOrErr.getError());
1223 return false;
1224 }
1225
1226 GLuint endByte = endByteOrErr.getResult();
1227
1228 if (pixelUnpackBuffer)
1229 {
1230 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1231 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1232 checkedEndByte += checkedOffset;
1233
1234 if (!checkedEndByte.IsValid() ||
1235 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1236 {
1237 // Overflow past the end of the buffer
1238 context->handleError(Error(GL_INVALID_OPERATION));
1239 return false;
1240 }
1241 }
1242 else
1243 {
1244 ASSERT(imageSize >= 0);
1245 if (pixels == nullptr && imageSize != 0)
1246 {
1247 context->handleError(
1248 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
1249 }
1250
1251 if (endByte > static_cast<GLuint>(imageSize))
1252 {
1253 context->handleError(
1254 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1255 return false;
1256 }
1257 }
1258
1259 return true;
1260}
1261
Geoff Lang37dde692014-01-31 16:34:54 -05001262bool ValidQueryType(const Context *context, GLenum queryType)
1263{
Geoff Langd4475812015-03-18 10:53:05 -04001264 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
1265 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 -05001266
1267 switch (queryType)
1268 {
1269 case GL_ANY_SAMPLES_PASSED:
1270 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1271 return true;
1272 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
Martin Radev1be913c2016-07-11 17:59:16 +03001273 return (context->getClientMajorVersion() >= 3);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001274 case GL_TIME_ELAPSED_EXT:
1275 return context->getExtensions().disjointTimerQuery;
Geoff Lang2b4ce802016-04-28 13:34:50 -04001276 case GL_COMMANDS_COMPLETED_CHROMIUM:
1277 return context->getExtensions().syncQuery;
Geoff Lang37dde692014-01-31 16:34:54 -05001278 default:
1279 return false;
1280 }
1281}
1282
Jamie Madillef300b12016-10-07 15:12:09 -04001283Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001284{
1285 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
1286 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
1287 // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
1288
Dian Xiang769769a2015-09-09 15:20:08 -07001289 Program *validProgram = context->getProgram(id);
1290
1291 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001292 {
Dian Xiang769769a2015-09-09 15:20:08 -07001293 if (context->getShader(id))
1294 {
Jamie Madill437fa652016-05-03 15:13:24 -04001295 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001296 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1297 }
1298 else
1299 {
Jamie Madill437fa652016-05-03 15:13:24 -04001300 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001301 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001302 }
Dian Xiang769769a2015-09-09 15:20:08 -07001303
1304 return validProgram;
1305}
1306
Jamie Madillef300b12016-10-07 15:12:09 -04001307Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001308{
1309 // See ValidProgram for spec details.
1310
1311 Shader *validShader = context->getShader(id);
1312
1313 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001314 {
Dian Xiang769769a2015-09-09 15:20:08 -07001315 if (context->getProgram(id))
1316 {
Jamie Madill437fa652016-05-03 15:13:24 -04001317 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001318 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1319 }
1320 else
1321 {
Jamie Madill437fa652016-05-03 15:13:24 -04001322 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001323 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001324 }
Dian Xiang769769a2015-09-09 15:20:08 -07001325
1326 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001327}
1328
Geoff Langb1196682014-07-23 13:47:29 -04001329bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001330{
1331 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1332 {
1333 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1334
Geoff Langaae65a42014-05-26 12:43:44 -04001335 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001336 {
Jamie Madill437fa652016-05-03 15:13:24 -04001337 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001338 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001339 }
1340 }
1341 else
1342 {
1343 switch (attachment)
1344 {
1345 case GL_DEPTH_ATTACHMENT:
1346 case GL_STENCIL_ATTACHMENT:
Martin Radev1be913c2016-07-11 17:59:16 +03001347 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001348
1349 case GL_DEPTH_STENCIL_ATTACHMENT:
Geoff Langc287ea62016-09-16 14:46:51 -04001350 if (!context->getExtensions().webglCompatibility &&
1351 context->getClientMajorVersion() < 3)
Martin Radev1be913c2016-07-11 17:59:16 +03001352 {
1353 context->handleError(Error(GL_INVALID_ENUM));
1354 return false;
1355 }
1356 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001357
1358 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001359 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03001360 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001361 }
1362 }
1363
1364 return true;
1365}
1366
Corentin Walleze0902642014-11-04 12:32:15 -08001367bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
1368 GLenum internalformat, GLsizei width, GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001369{
1370 switch (target)
1371 {
1372 case GL_RENDERBUFFER:
1373 break;
1374 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001375 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001376 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001377 }
1378
1379 if (width < 0 || height < 0 || samples < 0)
1380 {
Jamie Madill437fa652016-05-03 15:13:24 -04001381 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001382 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001383 }
1384
Geoff Langd87878e2014-09-19 15:42:59 -04001385 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1386 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001387 {
Jamie Madill437fa652016-05-03 15:13:24 -04001388 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001389 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 }
1391
1392 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1393 // 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 -08001394 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001395 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001396 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 {
Jamie Madill437fa652016-05-03 15:13:24 -04001398 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001399 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001400 }
1401
Geoff Langaae65a42014-05-26 12:43:44 -04001402 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001403 {
Jamie Madill437fa652016-05-03 15:13:24 -04001404 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001405 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001406 }
1407
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001408 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001409 if (handle == 0)
1410 {
Jamie Madill437fa652016-05-03 15:13:24 -04001411 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001412 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001413 }
1414
1415 return true;
1416}
1417
Corentin Walleze0902642014-11-04 12:32:15 -08001418bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
1419 GLenum internalformat, GLsizei width, GLsizei height)
1420{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001421 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001422
1423 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001424 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001425 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001426 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001427 {
Jamie Madill437fa652016-05-03 15:13:24 -04001428 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001429 return false;
1430 }
1431
1432 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1433 // the specified storage. This is different than ES 3.0 in which a sample number higher
1434 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001435 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001436 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001437 {
Geoff Langa4903b72015-03-02 16:02:48 -08001438 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1439 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1440 {
Jamie Madill437fa652016-05-03 15:13:24 -04001441 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001442 return false;
1443 }
Corentin Walleze0902642014-11-04 12:32:15 -08001444 }
1445
1446 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
1447}
1448
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001449bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
1450 GLenum renderbuffertarget, GLuint renderbuffer)
1451{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001452 if (!ValidFramebufferTarget(target))
1453 {
Jamie Madill437fa652016-05-03 15:13:24 -04001454 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001455 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001456 }
1457
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001458 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001459
Jamie Madill84115c92015-04-23 15:00:07 -04001460 ASSERT(framebuffer);
1461 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001462 {
Jamie Madill437fa652016-05-03 15:13:24 -04001463 context->handleError(
1464 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001465 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001466 }
1467
Jamie Madillb4472272014-07-03 10:38:55 -04001468 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001469 {
Jamie Madillb4472272014-07-03 10:38:55 -04001470 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001471 }
1472
Jamie Madillab9d82c2014-01-21 16:38:14 -05001473 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1474 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1475 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1476 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1477 if (renderbuffer != 0)
1478 {
1479 if (!context->getRenderbuffer(renderbuffer))
1480 {
Jamie Madill437fa652016-05-03 15:13:24 -04001481 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001482 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001483 }
1484 }
1485
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001486 return true;
1487}
1488
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001489bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001490 GLint srcX0,
1491 GLint srcY0,
1492 GLint srcX1,
1493 GLint srcY1,
1494 GLint dstX0,
1495 GLint dstY0,
1496 GLint dstX1,
1497 GLint dstY1,
1498 GLbitfield mask,
1499 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001500{
1501 switch (filter)
1502 {
1503 case GL_NEAREST:
1504 break;
1505 case GL_LINEAR:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001506 break;
1507 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001508 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001509 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001510 }
1511
1512 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1513 {
Jamie Madill437fa652016-05-03 15:13:24 -04001514 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001515 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001516 }
1517
1518 if (mask == 0)
1519 {
1520 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1521 // buffers are copied.
1522 return false;
1523 }
1524
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001525 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1526 // color buffer, leaving only nearest being unfiltered from above
1527 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1528 {
Jamie Madill437fa652016-05-03 15:13:24 -04001529 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001530 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001531 }
1532
Jamie Madill51f40ec2016-06-15 14:06:00 -04001533 const auto &glState = context->getGLState();
1534 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1535 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001536
1537 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001538 {
Jamie Madill437fa652016-05-03 15:13:24 -04001539 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001540 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001541 }
1542
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001543 if (readFramebuffer->id() == drawFramebuffer->id())
1544 {
1545 context->handleError(Error(GL_INVALID_OPERATION));
1546 return false;
1547 }
1548
Jamie Madill51f40ec2016-06-15 14:06:00 -04001549 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001550 {
Jamie Madill437fa652016-05-03 15:13:24 -04001551 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001552 return false;
1553 }
1554
Jamie Madill51f40ec2016-06-15 14:06:00 -04001555 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001556 {
Jamie Madill437fa652016-05-03 15:13:24 -04001557 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001558 return false;
1559 }
1560
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001561 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001562 {
Jamie Madill437fa652016-05-03 15:13:24 -04001563 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001564 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001565 }
1566
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001567 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1568
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001569 if (mask & GL_COLOR_BUFFER_BIT)
1570 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001571 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1572 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001573 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001574
1575 if (readColorBuffer && drawColorBuffer)
1576 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001577 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001578
Geoff Langa15472a2015-08-11 11:48:03 -04001579 for (size_t drawbufferIdx = 0;
1580 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001581 {
Geoff Langa15472a2015-08-11 11:48:03 -04001582 const FramebufferAttachment *attachment =
1583 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1584 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001585 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001586 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001587
Geoff Langb2f3d052013-08-13 12:49:27 -04001588 // The GL ES 3.0.2 spec (pg 193) states that:
1589 // 1) If the read buffer is fixed point format, the draw buffer must be as well
1590 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
1591 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
Jamie Madill6163c752015-12-07 16:32:59 -05001592 // Changes with EXT_color_buffer_float:
1593 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001594 GLenum readComponentType = readFormat.info->componentType;
1595 GLenum drawComponentType = drawFormat.info->componentType;
Jamie Madill6163c752015-12-07 16:32:59 -05001596 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1597 readComponentType == GL_SIGNED_NORMALIZED);
1598 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1599 drawComponentType == GL_SIGNED_NORMALIZED);
1600
1601 if (extensions.colorBufferFloat)
1602 {
1603 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1604 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1605
1606 if (readFixedOrFloat != drawFixedOrFloat)
1607 {
Jamie Madill437fa652016-05-03 15:13:24 -04001608 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001609 "If the read buffer contains fixed-point or "
1610 "floating-point values, the draw buffer "
1611 "must as well."));
1612 return false;
1613 }
1614 }
1615 else if (readFixedPoint != drawFixedPoint)
1616 {
Jamie Madill437fa652016-05-03 15:13:24 -04001617 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001618 "If the read buffer contains fixed-point "
1619 "values, the draw buffer must as well."));
1620 return false;
1621 }
1622
1623 if (readComponentType == GL_UNSIGNED_INT &&
1624 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001625 {
Jamie Madill437fa652016-05-03 15:13:24 -04001626 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001627 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001628 }
1629
Jamie Madill6163c752015-12-07 16:32:59 -05001630 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001631 {
Jamie Madill437fa652016-05-03 15:13:24 -04001632 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001633 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001634 }
1635
Jamie Madilla3944d42016-07-22 22:13:26 -04001636 if (readColorBuffer->getSamples() > 0 &&
1637 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001638 {
Jamie Madill437fa652016-05-03 15:13:24 -04001639 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001640 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001641 }
1642 }
1643 }
1644
Jamie Madilla3944d42016-07-22 22:13:26 -04001645 if ((readFormat.info->componentType == GL_INT ||
1646 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1647 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001648 {
Jamie Madill437fa652016-05-03 15:13:24 -04001649 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001650 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001651 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001652 }
1653 }
1654
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001655 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1656 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1657 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001658 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001659 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001660 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001661 const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
1662 const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001663
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001664 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001665 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001666 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001667 {
Jamie Madill437fa652016-05-03 15:13:24 -04001668 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001669 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001670 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001671
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001672 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001673 {
Jamie Madill437fa652016-05-03 15:13:24 -04001674 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001675 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001676 }
1677 }
1678 }
1679 }
1680
1681 return true;
1682}
1683
Geoff Langb1196682014-07-23 13:47:29 -04001684bool ValidateGetVertexAttribParameters(Context *context, GLenum pname)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001685{
1686 switch (pname)
1687 {
1688 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1689 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1690 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1691 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1692 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1693 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1694 case GL_CURRENT_VERTEX_ATTRIB:
Martin Radev1be913c2016-07-11 17:59:16 +03001695 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001696
1697 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
Martin Radev1be913c2016-07-11 17:59:16 +03001698 // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses
1699 // the same constant.
1700 static_assert(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1701 "ANGLE extension enums not equal to GL enums.");
1702 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001703
1704 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
Martin Radev1be913c2016-07-11 17:59:16 +03001705 if (context->getClientMajorVersion() < 3)
1706 {
1707 context->handleError(Error(GL_INVALID_ENUM));
1708 return false;
1709 }
1710 return true;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001711
1712 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001713 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03001714 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001715 }
1716}
1717
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001718bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001719 GLint x,
1720 GLint y,
1721 GLsizei width,
1722 GLsizei height,
1723 GLenum format,
1724 GLenum type,
1725 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05001726{
Geoff Lang62fce5b2016-09-30 10:46:35 -04001727 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
1728}
1729
1730bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
1731 GLint x,
1732 GLint y,
1733 GLsizei width,
1734 GLsizei height,
1735 GLenum format,
1736 GLenum type,
1737 GLsizei bufSize,
1738 GLsizei *length,
1739 GLvoid *pixels)
1740{
1741 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001742 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001743 return false;
1744 }
1745
Geoff Lang62fce5b2016-09-30 10:46:35 -04001746 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1747 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001748 {
Geoff Langb1196682014-07-23 13:47:29 -04001749 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001750 }
1751
Geoff Lang62fce5b2016-09-30 10:46:35 -04001752 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001753 {
Geoff Langb1196682014-07-23 13:47:29 -04001754 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001755 }
1756
Jamie Madillc29968b2016-01-20 11:17:23 -05001757 return true;
1758}
1759
1760bool ValidateReadnPixelsEXT(Context *context,
1761 GLint x,
1762 GLint y,
1763 GLsizei width,
1764 GLsizei height,
1765 GLenum format,
1766 GLenum type,
1767 GLsizei bufSize,
1768 GLvoid *pixels)
1769{
1770 if (bufSize < 0)
1771 {
Jamie Madill437fa652016-05-03 15:13:24 -04001772 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001773 return false;
1774 }
1775
Geoff Lang62fce5b2016-09-30 10:46:35 -04001776 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
1777 pixels);
1778}
Jamie Madill26e91952014-03-05 15:01:27 -05001779
Geoff Lang62fce5b2016-09-30 10:46:35 -04001780bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
1781 GLint x,
1782 GLint y,
1783 GLsizei width,
1784 GLsizei height,
1785 GLenum format,
1786 GLenum type,
1787 GLsizei bufSize,
1788 GLsizei *length,
1789 GLvoid *data)
1790{
1791 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001792 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001793 return false;
1794 }
1795
Geoff Lang62fce5b2016-09-30 10:46:35 -04001796 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001797 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001798 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001799 }
1800
Geoff Lang62fce5b2016-09-30 10:46:35 -04001801 if (!ValidateRobustBufferSize(context, bufSize, *length))
1802 {
1803 return false;
1804 }
1805
1806 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001807}
1808
Olli Etuaho41997e72016-03-10 13:38:39 +02001809bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001810{
1811 if (!context->getExtensions().occlusionQueryBoolean &&
1812 !context->getExtensions().disjointTimerQuery)
1813 {
Jamie Madill437fa652016-05-03 15:13:24 -04001814 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001815 return false;
1816 }
1817
Olli Etuaho41997e72016-03-10 13:38:39 +02001818 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001819}
1820
Olli Etuaho41997e72016-03-10 13:38:39 +02001821bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001822{
1823 if (!context->getExtensions().occlusionQueryBoolean &&
1824 !context->getExtensions().disjointTimerQuery)
1825 {
Jamie Madill437fa652016-05-03 15:13:24 -04001826 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001827 return false;
1828 }
1829
Olli Etuaho41997e72016-03-10 13:38:39 +02001830 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001831}
1832
1833bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001834{
1835 if (!ValidQueryType(context, target))
1836 {
Jamie Madill437fa652016-05-03 15:13:24 -04001837 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001838 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001839 }
1840
1841 if (id == 0)
1842 {
Jamie Madill437fa652016-05-03 15:13:24 -04001843 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04001844 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001845 }
1846
1847 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1848 // of zero, if the active query object name for <target> is non-zero (for the
1849 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1850 // the active query for either target is non-zero), if <id> is the name of an
1851 // existing query object whose type does not match <target>, or if <id> is the
1852 // active query object name for any query type, the error INVALID_OPERATION is
1853 // generated.
1854
1855 // Ensure no other queries are active
1856 // NOTE: If other queries than occlusion are supported, we will need to check
1857 // separately that:
1858 // a) The query ID passed is not the current active query for any target/type
1859 // b) There are no active queries for the requested target (and in the case
1860 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1861 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001862
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001863 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001864 {
Jamie Madill437fa652016-05-03 15:13:24 -04001865 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04001866 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001867 }
1868
1869 Query *queryObject = context->getQuery(id, true, target);
1870
1871 // check that name was obtained with glGenQueries
1872 if (!queryObject)
1873 {
Jamie Madill437fa652016-05-03 15:13:24 -04001874 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04001875 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001876 }
1877
1878 // check for type mismatch
1879 if (queryObject->getType() != target)
1880 {
Jamie Madill437fa652016-05-03 15:13:24 -04001881 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04001882 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001883 }
1884
1885 return true;
1886}
1887
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001888bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1889{
1890 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001891 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001892 {
Jamie Madill437fa652016-05-03 15:13:24 -04001893 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001894 return false;
1895 }
1896
1897 return ValidateBeginQueryBase(context, target, id);
1898}
1899
1900bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001901{
1902 if (!ValidQueryType(context, target))
1903 {
Jamie Madill437fa652016-05-03 15:13:24 -04001904 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001905 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001906 }
1907
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001908 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001909
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001910 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001911 {
Jamie Madill437fa652016-05-03 15:13:24 -04001912 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04001913 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001914 }
1915
Jamie Madill45c785d2014-05-13 14:09:34 -04001916 return true;
1917}
1918
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001919bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1920{
1921 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001922 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001923 {
Jamie Madill437fa652016-05-03 15:13:24 -04001924 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001925 return false;
1926 }
1927
1928 return ValidateEndQueryBase(context, target);
1929}
1930
1931bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1932{
1933 if (!context->getExtensions().disjointTimerQuery)
1934 {
Jamie Madill437fa652016-05-03 15:13:24 -04001935 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001936 return false;
1937 }
1938
1939 if (target != GL_TIMESTAMP_EXT)
1940 {
Jamie Madill437fa652016-05-03 15:13:24 -04001941 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001942 return false;
1943 }
1944
1945 Query *queryObject = context->getQuery(id, true, target);
1946 if (queryObject == nullptr)
1947 {
Jamie Madill437fa652016-05-03 15:13:24 -04001948 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001949 return false;
1950 }
1951
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001952 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001953 {
Jamie Madill437fa652016-05-03 15:13:24 -04001954 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001955 return false;
1956 }
1957
1958 return true;
1959}
1960
1961bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname)
1962{
1963 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1964 {
Jamie Madill437fa652016-05-03 15:13:24 -04001965 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001966 return false;
1967 }
1968
1969 switch (pname)
1970 {
1971 case GL_CURRENT_QUERY_EXT:
1972 if (target == GL_TIMESTAMP_EXT)
1973 {
Jamie Madill437fa652016-05-03 15:13:24 -04001974 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001975 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
1976 return false;
1977 }
1978 break;
1979 case GL_QUERY_COUNTER_BITS_EXT:
1980 if (!context->getExtensions().disjointTimerQuery ||
1981 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1982 {
Jamie Madill437fa652016-05-03 15:13:24 -04001983 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001984 return false;
1985 }
1986 break;
1987 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001988 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001989 return false;
1990 }
1991
1992 return true;
1993}
1994
1995bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1996{
1997 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001998 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001999 {
Jamie Madill437fa652016-05-03 15:13:24 -04002000 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002001 return false;
2002 }
2003
2004 return ValidateGetQueryivBase(context, target, pname);
2005}
2006
2007bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname)
2008{
2009 Query *queryObject = context->getQuery(id, false, GL_NONE);
2010
2011 if (!queryObject)
2012 {
Jamie Madill437fa652016-05-03 15:13:24 -04002013 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002014 return false;
2015 }
2016
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002017 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002018 {
Jamie Madill437fa652016-05-03 15:13:24 -04002019 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002020 return false;
2021 }
2022
2023 switch (pname)
2024 {
2025 case GL_QUERY_RESULT_EXT:
2026 case GL_QUERY_RESULT_AVAILABLE_EXT:
2027 break;
2028
2029 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002030 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002031 return false;
2032 }
2033
2034 return true;
2035}
2036
2037bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2038{
2039 if (!context->getExtensions().disjointTimerQuery)
2040 {
Jamie Madill437fa652016-05-03 15:13:24 -04002041 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002042 return false;
2043 }
2044 return ValidateGetQueryObjectValueBase(context, id, pname);
2045}
2046
2047bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2048{
2049 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002050 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002051 {
Jamie Madill437fa652016-05-03 15:13:24 -04002052 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002053 return false;
2054 }
2055 return ValidateGetQueryObjectValueBase(context, id, pname);
2056}
2057
2058bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2059{
2060 if (!context->getExtensions().disjointTimerQuery)
2061 {
Jamie Madill437fa652016-05-03 15:13:24 -04002062 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002063 return false;
2064 }
2065 return ValidateGetQueryObjectValueBase(context, id, pname);
2066}
2067
2068bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2069{
2070 if (!context->getExtensions().disjointTimerQuery)
2071 {
Jamie Madill437fa652016-05-03 15:13:24 -04002072 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002073 return false;
2074 }
2075 return ValidateGetQueryObjectValueBase(context, id, pname);
2076}
2077
Jamie Madill62d31cb2015-09-11 13:25:51 -04002078static bool ValidateUniformCommonBase(gl::Context *context,
2079 GLenum targetUniformType,
2080 GLint location,
2081 GLsizei count,
2082 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002083{
2084 if (count < 0)
2085 {
Jamie Madill437fa652016-05-03 15:13:24 -04002086 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002087 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002088 }
2089
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002090 gl::Program *program = context->getGLState().getProgram();
Geoff Lang7dd2e102014-11-10 15:19:26 -05002091 if (!program)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002092 {
Jamie Madill437fa652016-05-03 15:13:24 -04002093 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002094 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002095 }
2096
Geoff Langd8605522016-04-13 10:19:12 -04002097 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002098 {
2099 // Silently ignore the uniform command
2100 return false;
2101 }
2102
Geoff Lang7dd2e102014-11-10 15:19:26 -05002103 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002104 {
Jamie Madill437fa652016-05-03 15:13:24 -04002105 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002106 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002107 }
2108
Jamie Madill62d31cb2015-09-11 13:25:51 -04002109 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002110
2111 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002112 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002113 {
Jamie Madill437fa652016-05-03 15:13:24 -04002114 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002115 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002116 }
2117
Jamie Madill62d31cb2015-09-11 13:25:51 -04002118 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002119 return true;
2120}
2121
Jamie Madillaa981bd2014-05-20 10:55:55 -04002122bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2123{
2124 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002125 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2126 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002127 {
Jamie Madill437fa652016-05-03 15:13:24 -04002128 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002129 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002130 }
2131
Jamie Madill62d31cb2015-09-11 13:25:51 -04002132 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002133 if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
2134 {
2135 return false;
2136 }
2137
Jamie Madillf2575982014-06-25 16:04:54 -04002138 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002139 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002140 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2141 {
Jamie Madill437fa652016-05-03 15:13:24 -04002142 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002143 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002144 }
2145
2146 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002147}
2148
2149bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
2150 GLboolean transpose)
2151{
2152 // Check for ES3 uniform entry points
2153 int rows = VariableRowCount(matrixType);
2154 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002155 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002156 {
Jamie Madill437fa652016-05-03 15:13:24 -04002157 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002158 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002159 }
2160
Martin Radev1be913c2016-07-11 17:59:16 +03002161 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002162 {
Jamie Madill437fa652016-05-03 15:13:24 -04002163 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002164 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002165 }
2166
Jamie Madill62d31cb2015-09-11 13:25:51 -04002167 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002168 if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
2169 {
2170 return false;
2171 }
2172
2173 if (uniform->type != matrixType)
2174 {
Jamie Madill437fa652016-05-03 15:13:24 -04002175 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002176 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002177 }
2178
2179 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002180}
2181
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002182bool ValidateStateQuery(ValidationContext *context,
2183 GLenum pname,
2184 GLenum *nativeType,
2185 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002186{
2187 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2188 {
Jamie Madill437fa652016-05-03 15:13:24 -04002189 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002190 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002191 }
2192
Jamie Madill0af26e12015-03-05 19:54:33 -05002193 const Caps &caps = context->getCaps();
2194
Jamie Madill893ab082014-05-16 16:56:10 -04002195 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2196 {
2197 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2198
Jamie Madill0af26e12015-03-05 19:54:33 -05002199 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002200 {
Jamie Madill437fa652016-05-03 15:13:24 -04002201 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002202 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002203 }
2204 }
2205
2206 switch (pname)
2207 {
2208 case GL_TEXTURE_BINDING_2D:
2209 case GL_TEXTURE_BINDING_CUBE_MAP:
2210 case GL_TEXTURE_BINDING_3D:
2211 case GL_TEXTURE_BINDING_2D_ARRAY:
Jamie Madill893ab082014-05-16 16:56:10 -04002212 break;
Ian Ewell54f87462016-03-10 13:47:21 -05002213 case GL_TEXTURE_BINDING_EXTERNAL_OES:
John Bauman18319182016-09-28 14:22:27 -07002214 if (!context->getExtensions().eglStreamConsumerExternal &&
2215 !context->getExtensions().eglImageExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002216 {
John Bauman18319182016-09-28 14:22:27 -07002217 context->handleError(Error(GL_INVALID_ENUM,
2218 "Neither NV_EGL_stream_consumer_external nor "
2219 "GL_OES_EGL_image_external extensions enabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002220 return false;
2221 }
2222 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002223
2224 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2225 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2226 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002227 if (context->getGLState().getReadFramebuffer()->checkStatus(
2228 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002229 {
Jamie Madill437fa652016-05-03 15:13:24 -04002230 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002231 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002232 }
2233
Jamie Madill51f40ec2016-06-15 14:06:00 -04002234 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2235 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002236
2237 if (framebuffer->getReadBufferState() == GL_NONE)
2238 {
2239 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2240 return false;
2241 }
2242
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002243 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002244 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002245 {
Jamie Madill437fa652016-05-03 15:13:24 -04002246 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002247 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002248 }
2249 }
2250 break;
2251
2252 default:
2253 break;
2254 }
2255
2256 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002257 if (*numParams == 0)
2258 {
2259 return false;
2260 }
2261
2262 return true;
2263}
2264
2265bool ValidateRobustStateQuery(ValidationContext *context,
2266 GLenum pname,
2267 GLsizei bufSize,
2268 GLenum *nativeType,
2269 unsigned int *numParams)
2270{
2271 if (!ValidateRobustEntryPoint(context, bufSize))
2272 {
2273 return false;
2274 }
2275
2276 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2277 {
2278 return false;
2279 }
2280
2281 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002282 {
2283 return false;
2284 }
2285
2286 return true;
2287}
2288
Jamie Madillc29968b2016-01-20 11:17:23 -05002289bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2290 GLenum target,
2291 GLint level,
2292 GLenum internalformat,
2293 bool isSubImage,
2294 GLint xoffset,
2295 GLint yoffset,
2296 GLint zoffset,
2297 GLint x,
2298 GLint y,
2299 GLsizei width,
2300 GLsizei height,
2301 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002302 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002303{
Jamie Madill560a8d82014-05-21 13:06:20 -04002304 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2305 {
Jamie Madill437fa652016-05-03 15:13:24 -04002306 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002307 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002308 }
2309
2310 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
2311 {
Jamie Madill437fa652016-05-03 15:13:24 -04002312 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002313 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002314 }
2315
2316 if (border != 0)
2317 {
Jamie Madill437fa652016-05-03 15:13:24 -04002318 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002319 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002320 }
2321
2322 if (!ValidMipLevel(context, target, level))
2323 {
Jamie Madill437fa652016-05-03 15:13:24 -04002324 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002325 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002326 }
2327
Jamie Madill51f40ec2016-06-15 14:06:00 -04002328 const auto &state = context->getGLState();
2329 auto readFramebuffer = state.getReadFramebuffer();
2330 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002331 {
Jamie Madill437fa652016-05-03 15:13:24 -04002332 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002333 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002334 }
2335
Jamie Madill51f40ec2016-06-15 14:06:00 -04002336 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002337 {
Jamie Madill437fa652016-05-03 15:13:24 -04002338 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002339 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002340 }
2341
Martin Radev138064f2016-07-15 12:03:41 +03002342 if (readFramebuffer->getReadBufferState() == GL_NONE)
2343 {
2344 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2345 return false;
2346 }
2347
Geoff Langaae65a42014-05-26 12:43:44 -04002348 const gl::Caps &caps = context->getCaps();
2349
Geoff Langaae65a42014-05-26 12:43:44 -04002350 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002351 switch (target)
2352 {
2353 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002354 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002355 break;
2356
2357 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2358 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2359 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2360 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2361 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2362 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002363 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002364 break;
2365
2366 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002367 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002368 break;
2369
2370 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002371 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002372 break;
2373
2374 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002375 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002376 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002377 }
2378
Jamie Madillc29968b2016-01-20 11:17:23 -05002379 gl::Texture *texture =
2380 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002381 if (!texture)
2382 {
Jamie Madill437fa652016-05-03 15:13:24 -04002383 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002384 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002385 }
2386
Geoff Lang69cce582015-09-17 13:20:36 -04002387 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002388 {
Jamie Madill437fa652016-05-03 15:13:24 -04002389 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002390 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002391 }
2392
Geoff Lang5d601382014-07-22 15:14:06 -04002393 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2394
2395 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002396 {
Jamie Madill437fa652016-05-03 15:13:24 -04002397 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002398 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002399 }
2400
Geoff Langa9be0dc2014-12-17 12:34:40 -05002401 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04002402 {
Jamie Madill437fa652016-05-03 15:13:24 -04002403 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002404 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002405 }
2406
2407 if (isSubImage)
2408 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002409 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2410 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2411 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002412 {
Jamie Madill437fa652016-05-03 15:13:24 -04002413 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002414 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002415 }
2416 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002417 else
2418 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002419 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002420 {
Jamie Madill437fa652016-05-03 15:13:24 -04002421 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002422 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002423 }
2424
Martin Radev1be913c2016-07-11 17:59:16 +03002425 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002426 {
Jamie Madill437fa652016-05-03 15:13:24 -04002427 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002428 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002429 }
2430
2431 int maxLevelDimension = (maxDimension >> level);
2432 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
2433 {
Jamie Madill437fa652016-05-03 15:13:24 -04002434 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002435 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002436 }
2437 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002438
Jamie Madill0c8abca2016-07-22 20:21:26 -04002439 if (textureFormatOut)
2440 {
2441 *textureFormatOut = texture->getFormat(target, level);
2442 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002443 return true;
2444}
2445
Jamie Madillf25855c2015-11-03 11:06:18 -05002446static bool ValidateDrawBase(ValidationContext *context,
2447 GLenum mode,
2448 GLsizei count,
2449 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002450{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002451 switch (mode)
2452 {
2453 case GL_POINTS:
2454 case GL_LINES:
2455 case GL_LINE_LOOP:
2456 case GL_LINE_STRIP:
2457 case GL_TRIANGLES:
2458 case GL_TRIANGLE_STRIP:
2459 case GL_TRIANGLE_FAN:
2460 break;
2461 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002462 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002463 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002464 }
2465
Jamie Madill250d33f2014-06-06 17:09:03 -04002466 if (count < 0)
2467 {
Jamie Madill437fa652016-05-03 15:13:24 -04002468 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002469 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002470 }
2471
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002472 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002473
Jamie Madill250d33f2014-06-06 17:09:03 -04002474 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002475 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002476 {
Jamie Madill437fa652016-05-03 15:13:24 -04002477 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002478 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002479 }
2480
Jamie Madill51f40ec2016-06-15 14:06:00 -04002481 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04002482 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04002483 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04002484 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
2485 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
2486 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
2487 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2488 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2489 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04002490 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04002491 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2492 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04002493 {
2494 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2495 // Section 6.10 of the WebGL 1.0 spec
2496 ERR(
2497 "This ANGLE implementation does not support separate front/back stencil "
2498 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04002499 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002500 return false;
2501 }
Jamie Madillac528012014-06-20 13:21:23 -04002502 }
2503
Jamie Madill51f40ec2016-06-15 14:06:00 -04002504 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002505 {
Jamie Madill437fa652016-05-03 15:13:24 -04002506 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002507 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002508 }
2509
Geoff Lang7dd2e102014-11-10 15:19:26 -05002510 gl::Program *program = state.getProgram();
2511 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002512 {
Jamie Madill437fa652016-05-03 15:13:24 -04002513 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002514 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002515 }
2516
Geoff Lang7dd2e102014-11-10 15:19:26 -05002517 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002518 {
Jamie Madill437fa652016-05-03 15:13:24 -04002519 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002520 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002521 }
2522
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002523 // Uniform buffer validation
2524 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2525 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002526 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002527 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002528 const OffsetBindingPointer<Buffer> &uniformBuffer =
2529 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002530
Geoff Lang5d124a62015-09-15 13:03:27 -04002531 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002532 {
2533 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002534 context->handleError(
2535 Error(GL_INVALID_OPERATION,
2536 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002537 return false;
2538 }
2539
Geoff Lang5d124a62015-09-15 13:03:27 -04002540 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002541 if (uniformBufferSize == 0)
2542 {
2543 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002544 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002545 }
2546
Jamie Madill62d31cb2015-09-11 13:25:51 -04002547 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002548 {
2549 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002550 context->handleError(
2551 Error(GL_INVALID_OPERATION,
2552 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002553 return false;
2554 }
2555 }
2556
Jamie Madill250d33f2014-06-06 17:09:03 -04002557 // No-op if zero count
2558 return (count > 0);
2559}
2560
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002561bool ValidateDrawArrays(ValidationContext *context,
2562 GLenum mode,
2563 GLint first,
2564 GLsizei count,
2565 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002566{
Jamie Madillfd716582014-06-06 17:09:04 -04002567 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002568 {
Jamie Madill437fa652016-05-03 15:13:24 -04002569 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002570 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002571 }
2572
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002573 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002574 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002575 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
2576 curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002577 {
2578 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2579 // that does not match the current transform feedback object's draw mode (if transform feedback
2580 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002581 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002582 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002583 }
2584
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002585 if (!ValidateDrawBase(context, mode, count, primcount))
2586 {
2587 return false;
2588 }
2589
2590 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04002591 {
2592 return false;
2593 }
2594
2595 return true;
2596}
2597
Geoff Langb1196682014-07-23 13:47:29 -04002598bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002599{
2600 if (primcount < 0)
2601 {
Jamie Madill437fa652016-05-03 15:13:24 -04002602 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002603 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002604 }
2605
Jamie Madill2b976812014-08-25 15:47:49 -04002606 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04002607 {
2608 return false;
2609 }
2610
2611 // No-op if zero primitive count
2612 return (primcount > 0);
2613}
2614
Geoff Lang87a93302014-09-16 13:29:43 -04002615static bool ValidateDrawInstancedANGLE(Context *context)
2616{
2617 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002618 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04002619
Geoff Lang7dd2e102014-11-10 15:19:26 -05002620 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04002621
2622 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04002623 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04002624 {
2625 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04002626 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04002627 {
2628 return true;
2629 }
2630 }
2631
Jamie Madill437fa652016-05-03 15:13:24 -04002632 context->handleError(Error(GL_INVALID_OPERATION,
2633 "ANGLE_instanced_arrays requires that at least one active attribute"
2634 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04002635 return false;
2636}
2637
2638bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
2639{
2640 if (!ValidateDrawInstancedANGLE(context))
2641 {
2642 return false;
2643 }
2644
2645 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
2646}
2647
Jamie Madillf25855c2015-11-03 11:06:18 -05002648bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002649 GLenum mode,
2650 GLsizei count,
2651 GLenum type,
2652 const GLvoid *indices,
2653 GLsizei primcount,
2654 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002655{
Jamie Madill250d33f2014-06-06 17:09:03 -04002656 switch (type)
2657 {
2658 case GL_UNSIGNED_BYTE:
2659 case GL_UNSIGNED_SHORT:
Martin Radev1be913c2016-07-11 17:59:16 +03002660 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002661 case GL_UNSIGNED_INT:
Martin Radev1be913c2016-07-11 17:59:16 +03002662 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2663 {
2664 context->handleError(Error(GL_INVALID_ENUM));
2665 return false;
2666 }
2667 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002668 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002669 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03002670 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002671 }
2672
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002673 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002674
2675 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002676 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002677 {
2678 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
2679 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002680 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002681 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002682 }
2683
2684 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002685 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002686 {
Jamie Madill437fa652016-05-03 15:13:24 -04002687 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002688 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002689 }
2690
Jamie Madill2b976812014-08-25 15:47:49 -04002691 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002692 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04002693 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002694 {
Jamie Madill437fa652016-05-03 15:13:24 -04002695 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002696 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002697 }
2698
Jamie Madillae3000b2014-08-25 15:47:51 -04002699 if (elementArrayBuffer)
2700 {
2701 const gl::Type &typeInfo = gl::GetTypeInfo(type);
2702
2703 GLint64 offset = reinterpret_cast<GLint64>(indices);
2704 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
2705
2706 // check for integer overflows
2707 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
2708 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
2709 {
Jamie Madill437fa652016-05-03 15:13:24 -04002710 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04002711 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002712 }
2713
2714 // Check for reading past the end of the bound buffer object
2715 if (byteCount > elementArrayBuffer->getSize())
2716 {
Jamie Madill437fa652016-05-03 15:13:24 -04002717 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002718 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002719 }
2720 }
2721 else if (!indices)
2722 {
2723 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04002724 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002725 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002726 }
2727
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002728 if (!ValidateDrawBase(context, mode, count, primcount))
2729 {
2730 return false;
2731 }
2732
Jamie Madill2b976812014-08-25 15:47:49 -04002733 // Use max index to validate if our vertex buffers are large enough for the pull.
2734 // TODO: offer fast path, with disabled index validation.
2735 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
2736 if (elementArrayBuffer)
2737 {
Jacek Cabana5521de2014-10-01 17:23:46 +02002738 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04002739 Error error =
2740 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
2741 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04002742 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04002743 {
Jamie Madill437fa652016-05-03 15:13:24 -04002744 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04002745 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04002746 }
2747 }
2748 else
2749 {
Geoff Lang3edfe032015-09-04 16:38:24 -04002750 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04002751 }
2752
Jamie Madille79b1e12015-11-04 16:36:37 -05002753 // If we use an index greater than our maximum supported index range, return an error.
2754 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2755 // return an error if possible here.
2756 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
2757 {
Jamie Madill437fa652016-05-03 15:13:24 -04002758 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05002759 return false;
2760 }
2761
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04002762 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04002763 {
2764 return false;
2765 }
2766
Geoff Lang3edfe032015-09-04 16:38:24 -04002767 // No op if there are no real indices in the index data (all are primitive restart).
2768 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04002769}
2770
Geoff Langb1196682014-07-23 13:47:29 -04002771bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002772 GLenum mode,
2773 GLsizei count,
2774 GLenum type,
2775 const GLvoid *indices,
2776 GLsizei primcount,
2777 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002778{
2779 if (primcount < 0)
2780 {
Jamie Madill437fa652016-05-03 15:13:24 -04002781 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002782 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002783 }
2784
Jamie Madill2b976812014-08-25 15:47:49 -04002785 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04002786 {
2787 return false;
2788 }
2789
2790 // No-op zero primitive count
2791 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04002792}
2793
Geoff Lang3edfe032015-09-04 16:38:24 -04002794bool ValidateDrawElementsInstancedANGLE(Context *context,
2795 GLenum mode,
2796 GLsizei count,
2797 GLenum type,
2798 const GLvoid *indices,
2799 GLsizei primcount,
2800 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04002801{
2802 if (!ValidateDrawInstancedANGLE(context))
2803 {
2804 return false;
2805 }
2806
2807 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
2808}
2809
Geoff Langb1196682014-07-23 13:47:29 -04002810bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04002811 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002812{
Jamie Madill55ec3b12014-07-03 10:38:57 -04002813 if (!ValidFramebufferTarget(target))
2814 {
Jamie Madill437fa652016-05-03 15:13:24 -04002815 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002816 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002817 }
2818
2819 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002820 {
2821 return false;
2822 }
2823
Jamie Madill55ec3b12014-07-03 10:38:57 -04002824 if (texture != 0)
2825 {
2826 gl::Texture *tex = context->getTexture(texture);
2827
2828 if (tex == NULL)
2829 {
Jamie Madill437fa652016-05-03 15:13:24 -04002830 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002831 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002832 }
2833
2834 if (level < 0)
2835 {
Jamie Madill437fa652016-05-03 15:13:24 -04002836 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002837 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002838 }
2839 }
2840
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002841 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002842 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002843
Jamie Madill84115c92015-04-23 15:00:07 -04002844 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002845 {
Jamie Madill437fa652016-05-03 15:13:24 -04002846 context->handleError(
2847 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002848 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002849 }
2850
2851 return true;
2852}
2853
Geoff Langb1196682014-07-23 13:47:29 -04002854bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04002855 GLenum textarget, GLuint texture, GLint level)
2856{
Geoff Lang95663912015-04-02 15:54:45 -04002857 // 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 +03002858 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
2859 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002860 {
Jamie Madill437fa652016-05-03 15:13:24 -04002861 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002862 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002863 }
2864
2865 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04002866 {
2867 return false;
2868 }
2869
Jamie Madill55ec3b12014-07-03 10:38:57 -04002870 if (texture != 0)
2871 {
2872 gl::Texture *tex = context->getTexture(texture);
2873 ASSERT(tex);
2874
Jamie Madill2a6564e2014-07-11 09:53:19 -04002875 const gl::Caps &caps = context->getCaps();
2876
Jamie Madill55ec3b12014-07-03 10:38:57 -04002877 switch (textarget)
2878 {
2879 case GL_TEXTURE_2D:
2880 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04002881 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002882 {
Jamie Madill437fa652016-05-03 15:13:24 -04002883 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002884 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002885 }
2886 if (tex->getTarget() != GL_TEXTURE_2D)
2887 {
Jamie Madill437fa652016-05-03 15:13:24 -04002888 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002889 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002890 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002891 }
2892 break;
2893
2894 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2895 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2896 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2897 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2898 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2899 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2900 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04002901 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002902 {
Jamie Madill437fa652016-05-03 15:13:24 -04002903 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002904 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002905 }
2906 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
2907 {
Jamie Madill437fa652016-05-03 15:13:24 -04002908 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002909 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002910 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002911 }
2912 break;
2913
2914 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002915 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002916 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002917 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05002918
Jamie Madilla3944d42016-07-22 22:13:26 -04002919 const Format &format = tex->getFormat(textarget, level);
2920 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05002921 {
Jamie Madill437fa652016-05-03 15:13:24 -04002922 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002923 return false;
2924 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04002925 }
2926
Jamie Madill570f7c82014-07-03 10:38:54 -04002927 return true;
2928}
2929
Geoff Langb1196682014-07-23 13:47:29 -04002930bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002931{
2932 if (program == 0)
2933 {
Jamie Madill437fa652016-05-03 15:13:24 -04002934 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002935 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002936 }
2937
Dian Xiang769769a2015-09-09 15:20:08 -07002938 gl::Program *programObject = GetValidProgram(context, program);
2939 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05002940 {
2941 return false;
2942 }
2943
Jamie Madill0063c512014-08-25 15:47:53 -04002944 if (!programObject || !programObject->isLinked())
2945 {
Jamie Madill437fa652016-05-03 15:13:24 -04002946 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002947 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002948 }
2949
Geoff Lang7dd2e102014-11-10 15:19:26 -05002950 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04002951 {
Jamie Madill437fa652016-05-03 15:13:24 -04002952 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002953 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04002954 }
2955
Jamie Madill0063c512014-08-25 15:47:53 -04002956 return true;
2957}
2958
Geoff Langb1196682014-07-23 13:47:29 -04002959bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04002960{
2961 return ValidateGetUniformBase(context, program, location);
2962}
2963
Geoff Langb1196682014-07-23 13:47:29 -04002964bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04002965{
Jamie Madill78f41802014-08-25 15:47:55 -04002966 return ValidateGetUniformBase(context, program, location);
2967}
2968
Geoff Langf41d0ee2016-10-07 13:04:23 -04002969static bool ValidateSizedGetUniform(Context *context,
2970 GLuint program,
2971 GLint location,
2972 GLsizei bufSize,
2973 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04002974{
Geoff Langf41d0ee2016-10-07 13:04:23 -04002975 if (length)
2976 {
2977 *length = 0;
2978 }
2979
Jamie Madill78f41802014-08-25 15:47:55 -04002980 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04002981 {
Jamie Madill78f41802014-08-25 15:47:55 -04002982 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002983 }
2984
Geoff Langf41d0ee2016-10-07 13:04:23 -04002985 if (bufSize < 0)
2986 {
2987 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
2988 return false;
2989 }
2990
Jamie Madilla502c742014-08-28 17:19:13 -04002991 gl::Program *programObject = context->getProgram(program);
2992 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04002993
Jamie Madill78f41802014-08-25 15:47:55 -04002994 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04002995 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
2996 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04002997 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04002998 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04002999 context->handleError(
3000 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003001 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003002 }
3003
Geoff Langf41d0ee2016-10-07 13:04:23 -04003004 if (length)
3005 {
3006 // Cast is safe because of comparison to bufSize.
3007 *length = static_cast<GLsizei>(requiredBytes);
3008 }
3009
Jamie Madill0063c512014-08-25 15:47:53 -04003010 return true;
3011}
3012
Geoff Langb1196682014-07-23 13:47:29 -04003013bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003014{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003015 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003016}
3017
Geoff Langb1196682014-07-23 13:47:29 -04003018bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003019{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003020 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3021}
3022
3023bool ValidateGetUniformfvRobustANGLE(Context *context,
3024 GLuint program,
3025 GLint location,
3026 GLsizei bufSize,
3027 GLsizei *length,
3028 GLfloat *params)
3029{
3030 if (!ValidateRobustEntryPoint(context, bufSize))
3031 {
3032 return false;
3033 }
3034
3035 // bufSize is validated in ValidateSizedGetUniform
3036 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3037}
3038
3039bool ValidateGetUniformivRobustANGLE(Context *context,
3040 GLuint program,
3041 GLint location,
3042 GLsizei bufSize,
3043 GLsizei *length,
3044 GLint *params)
3045{
3046 if (!ValidateRobustEntryPoint(context, bufSize))
3047 {
3048 return false;
3049 }
3050
3051 // bufSize is validated in ValidateSizedGetUniform
3052 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3053}
3054
3055bool ValidateGetUniformuivRobustANGLE(Context *context,
3056 GLuint program,
3057 GLint location,
3058 GLsizei bufSize,
3059 GLsizei *length,
3060 GLuint *params)
3061{
3062 if (!ValidateRobustEntryPoint(context, bufSize))
3063 {
3064 return false;
3065 }
3066
3067 if (context->getClientMajorVersion() < 3)
3068 {
3069 context->handleError(
3070 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3071 return false;
3072 }
3073
3074 // bufSize is validated in ValidateSizedGetUniform
3075 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003076}
3077
Austin Kinross08332632015-05-05 13:35:47 -07003078bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
3079 const GLenum *attachments, bool defaultFramebuffer)
3080{
3081 if (numAttachments < 0)
3082 {
Jamie Madill437fa652016-05-03 15:13:24 -04003083 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003084 return false;
3085 }
3086
3087 for (GLsizei i = 0; i < numAttachments; ++i)
3088 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003089 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003090 {
3091 if (defaultFramebuffer)
3092 {
Jamie Madill437fa652016-05-03 15:13:24 -04003093 context->handleError(Error(
3094 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003095 return false;
3096 }
3097
3098 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3099 {
Jamie Madill437fa652016-05-03 15:13:24 -04003100 context->handleError(Error(GL_INVALID_OPERATION,
3101 "Requested color attachment is greater than the maximum "
3102 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003103 return false;
3104 }
3105 }
3106 else
3107 {
3108 switch (attachments[i])
3109 {
3110 case GL_DEPTH_ATTACHMENT:
3111 case GL_STENCIL_ATTACHMENT:
3112 case GL_DEPTH_STENCIL_ATTACHMENT:
3113 if (defaultFramebuffer)
3114 {
Jamie Madill437fa652016-05-03 15:13:24 -04003115 context->handleError(
3116 Error(GL_INVALID_ENUM,
3117 "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003118 return false;
3119 }
3120 break;
3121 case GL_COLOR:
3122 case GL_DEPTH:
3123 case GL_STENCIL:
3124 if (!defaultFramebuffer)
3125 {
Jamie Madill437fa652016-05-03 15:13:24 -04003126 context->handleError(
3127 Error(GL_INVALID_ENUM,
3128 "Invalid attachment when the default framebuffer is not bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003129 return false;
3130 }
3131 break;
3132 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003133 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003134 return false;
3135 }
3136 }
3137 }
3138
3139 return true;
3140}
3141
Austin Kinross6ee1e782015-05-29 17:05:37 -07003142bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3143{
3144 // Note that debug marker calls must not set error state
3145
3146 if (length < 0)
3147 {
3148 return false;
3149 }
3150
3151 if (marker == nullptr)
3152 {
3153 return false;
3154 }
3155
3156 return true;
3157}
3158
3159bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3160{
3161 // Note that debug marker calls must not set error state
3162
3163 if (length < 0)
3164 {
3165 return false;
3166 }
3167
3168 if (length > 0 && marker == nullptr)
3169 {
3170 return false;
3171 }
3172
3173 return true;
3174}
3175
Geoff Langdcab33b2015-07-21 13:03:16 -04003176bool ValidateEGLImageTargetTexture2DOES(Context *context,
3177 egl::Display *display,
3178 GLenum target,
3179 egl::Image *image)
3180{
Geoff Langa8406172015-07-21 16:53:39 -04003181 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3182 {
Jamie Madill437fa652016-05-03 15:13:24 -04003183 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003184 return false;
3185 }
3186
3187 switch (target)
3188 {
3189 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003190 if (!context->getExtensions().eglImage)
3191 {
3192 context->handleError(Error(
3193 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3194 }
3195 break;
3196
3197 case GL_TEXTURE_EXTERNAL_OES:
3198 if (!context->getExtensions().eglImageExternal)
3199 {
3200 context->handleError(Error(
3201 GL_INVALID_ENUM,
3202 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3203 }
Geoff Langa8406172015-07-21 16:53:39 -04003204 break;
3205
3206 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003207 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003208 return false;
3209 }
3210
3211 if (!display->isValidImage(image))
3212 {
Jamie Madill437fa652016-05-03 15:13:24 -04003213 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003214 return false;
3215 }
3216
3217 if (image->getSamples() > 0)
3218 {
Jamie Madill437fa652016-05-03 15:13:24 -04003219 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003220 "cannot create a 2D texture from a multisampled EGL image."));
3221 return false;
3222 }
3223
Jamie Madilla3944d42016-07-22 22:13:26 -04003224 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003225 if (!textureCaps.texturable)
3226 {
Jamie Madill437fa652016-05-03 15:13:24 -04003227 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003228 "EGL image internal format is not supported as a texture."));
3229 return false;
3230 }
3231
Geoff Langdcab33b2015-07-21 13:03:16 -04003232 return true;
3233}
3234
3235bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3236 egl::Display *display,
3237 GLenum target,
3238 egl::Image *image)
3239{
Geoff Langa8406172015-07-21 16:53:39 -04003240 if (!context->getExtensions().eglImage)
3241 {
Jamie Madill437fa652016-05-03 15:13:24 -04003242 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003243 return false;
3244 }
3245
3246 switch (target)
3247 {
3248 case GL_RENDERBUFFER:
3249 break;
3250
3251 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003252 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003253 return false;
3254 }
3255
3256 if (!display->isValidImage(image))
3257 {
Jamie Madill437fa652016-05-03 15:13:24 -04003258 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003259 return false;
3260 }
3261
Jamie Madilla3944d42016-07-22 22:13:26 -04003262 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003263 if (!textureCaps.renderable)
3264 {
Jamie Madill437fa652016-05-03 15:13:24 -04003265 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003266 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3267 return false;
3268 }
3269
Geoff Langdcab33b2015-07-21 13:03:16 -04003270 return true;
3271}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003272
3273bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3274{
Geoff Lang36167ab2015-12-07 10:27:14 -05003275 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003276 {
3277 // The default VAO should always exist
3278 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003279 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003280 return false;
3281 }
3282
3283 return true;
3284}
3285
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003286bool ValidateLinkProgram(Context *context, GLuint program)
3287{
3288 if (context->hasActiveTransformFeedback(program))
3289 {
3290 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003291 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003292 "Cannot link program while program is associated with an active "
3293 "transform feedback object."));
3294 return false;
3295 }
3296 return true;
3297}
3298
Geoff Langc5629752015-12-07 16:29:04 -05003299bool ValidateProgramBinaryBase(Context *context,
3300 GLuint program,
3301 GLenum binaryFormat,
3302 const void *binary,
3303 GLint length)
3304{
3305 Program *programObject = GetValidProgram(context, program);
3306 if (programObject == nullptr)
3307 {
3308 return false;
3309 }
3310
3311 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3312 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3313 programBinaryFormats.end())
3314 {
Jamie Madill437fa652016-05-03 15:13:24 -04003315 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003316 return false;
3317 }
3318
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003319 if (context->hasActiveTransformFeedback(program))
3320 {
3321 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003322 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003323 "Cannot change program binary while program is associated with "
3324 "an active transform feedback object."));
3325 return false;
3326 }
3327
Geoff Langc5629752015-12-07 16:29:04 -05003328 return true;
3329}
3330
3331bool ValidateGetProgramBinaryBase(Context *context,
3332 GLuint program,
3333 GLsizei bufSize,
3334 GLsizei *length,
3335 GLenum *binaryFormat,
3336 void *binary)
3337{
3338 Program *programObject = GetValidProgram(context, program);
3339 if (programObject == nullptr)
3340 {
3341 return false;
3342 }
3343
3344 if (!programObject->isLinked())
3345 {
Jamie Madill437fa652016-05-03 15:13:24 -04003346 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05003347 return false;
3348 }
3349
3350 return true;
3351}
Jamie Madillc29968b2016-01-20 11:17:23 -05003352
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003353bool ValidateUseProgram(Context *context, GLuint program)
3354{
3355 if (program != 0)
3356 {
3357 Program *programObject = context->getProgram(program);
3358 if (!programObject)
3359 {
3360 // ES 3.1.0 section 7.3 page 72
3361 if (context->getShader(program))
3362 {
Jamie Madill437fa652016-05-03 15:13:24 -04003363 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003364 Error(GL_INVALID_OPERATION,
3365 "Attempted to use a single shader instead of a shader program."));
3366 return false;
3367 }
3368 else
3369 {
Jamie Madill437fa652016-05-03 15:13:24 -04003370 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003371 return false;
3372 }
3373 }
3374 if (!programObject->isLinked())
3375 {
Jamie Madill437fa652016-05-03 15:13:24 -04003376 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003377 return false;
3378 }
3379 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003380 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003381 {
3382 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003383 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003384 Error(GL_INVALID_OPERATION,
3385 "Cannot change active program while transform feedback is unpaused."));
3386 return false;
3387 }
3388
3389 return true;
3390}
3391
Jamie Madillc29968b2016-01-20 11:17:23 -05003392bool ValidateCopyTexImage2D(ValidationContext *context,
3393 GLenum target,
3394 GLint level,
3395 GLenum internalformat,
3396 GLint x,
3397 GLint y,
3398 GLsizei width,
3399 GLsizei height,
3400 GLint border)
3401{
Martin Radev1be913c2016-07-11 17:59:16 +03003402 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003403 {
3404 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
3405 0, x, y, width, height, border);
3406 }
3407
Martin Radev1be913c2016-07-11 17:59:16 +03003408 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003409 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
3410 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003411}
Jamie Madillc29968b2016-01-20 11:17:23 -05003412
3413bool ValidateFramebufferRenderbuffer(Context *context,
3414 GLenum target,
3415 GLenum attachment,
3416 GLenum renderbuffertarget,
3417 GLuint renderbuffer)
3418{
3419 if (!ValidFramebufferTarget(target) ||
3420 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
3421 {
Jamie Madill437fa652016-05-03 15:13:24 -04003422 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05003423 return false;
3424 }
3425
3426 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
3427 renderbuffertarget, renderbuffer);
3428}
3429
3430bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3431{
3432 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3433 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3434 {
Jamie Madill437fa652016-05-03 15:13:24 -04003435 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003436 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
3437 return false;
3438 }
3439
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003440 ASSERT(context->getGLState().getDrawFramebuffer());
3441 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003442 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3443
3444 // This should come first before the check for the default frame buffer
3445 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3446 // rather than INVALID_OPERATION
3447 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3448 {
3449 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3450
3451 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003452 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3453 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003454 {
3455 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003456 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3457 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3458 // 3.1 is still a bit ambiguous about the error, but future specs are
3459 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04003460 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02003461 return false;
3462 }
3463 else if (bufs[colorAttachment] >= maxColorAttachment)
3464 {
Jamie Madill437fa652016-05-03 15:13:24 -04003465 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02003466 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05003467 return false;
3468 }
3469 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3470 frameBufferId != 0)
3471 {
3472 // INVALID_OPERATION-GL is bound to buffer and ith argument
3473 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04003474 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003475 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
3476 return false;
3477 }
3478 }
3479
3480 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3481 // and n is not 1 or bufs is bound to value other than BACK and NONE
3482 if (frameBufferId == 0)
3483 {
3484 if (n != 1)
3485 {
Jamie Madill437fa652016-05-03 15:13:24 -04003486 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05003487 "n must be 1 when GL is bound to the default framebuffer"));
3488 return false;
3489 }
3490
3491 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3492 {
Jamie Madill437fa652016-05-03 15:13:24 -04003493 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05003494 GL_INVALID_OPERATION,
3495 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
3496 return false;
3497 }
3498 }
3499
3500 return true;
3501}
3502
3503bool ValidateCopyTexSubImage2D(Context *context,
3504 GLenum target,
3505 GLint level,
3506 GLint xoffset,
3507 GLint yoffset,
3508 GLint x,
3509 GLint y,
3510 GLsizei width,
3511 GLsizei height)
3512{
Martin Radev1be913c2016-07-11 17:59:16 +03003513 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003514 {
3515 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
3516 yoffset, x, y, width, height, 0);
3517 }
3518
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003519 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
3520 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05003521}
3522
Olli Etuaho4f667482016-03-30 15:56:35 +03003523bool ValidateGetBufferPointervBase(Context *context, GLenum target, GLenum pname, void **params)
3524{
3525 if (!ValidBufferTarget(context, target))
3526 {
Jamie Madill437fa652016-05-03 15:13:24 -04003527 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03003528 return false;
3529 }
3530
3531 if (pname != GL_BUFFER_MAP_POINTER)
3532 {
Jamie Madill437fa652016-05-03 15:13:24 -04003533 context->handleError(Error(GL_INVALID_ENUM, "pname not valid: 0x%X", pname));
Olli Etuaho4f667482016-03-30 15:56:35 +03003534 return false;
3535 }
3536
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003537 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003538
3539 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3540 // target bound to zero generate an INVALID_OPERATION error."
3541 // GLES 3.1 section 6.6 explicitly specifies this error.
3542 if (!buffer)
3543 {
Jamie Madill437fa652016-05-03 15:13:24 -04003544 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003545 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
3546 return false;
3547 }
3548
3549 return true;
3550}
3551
3552bool ValidateUnmapBufferBase(Context *context, GLenum target)
3553{
3554 if (!ValidBufferTarget(context, target))
3555 {
Jamie Madill437fa652016-05-03 15:13:24 -04003556 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003557 return false;
3558 }
3559
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003560 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003561
3562 if (buffer == nullptr || !buffer->isMapped())
3563 {
Jamie Madill437fa652016-05-03 15:13:24 -04003564 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003565 return false;
3566 }
3567
3568 return true;
3569}
3570
3571bool ValidateMapBufferRangeBase(Context *context,
3572 GLenum target,
3573 GLintptr offset,
3574 GLsizeiptr length,
3575 GLbitfield access)
3576{
3577 if (!ValidBufferTarget(context, target))
3578 {
Jamie Madill437fa652016-05-03 15:13:24 -04003579 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003580 return false;
3581 }
3582
3583 if (offset < 0 || length < 0)
3584 {
Jamie Madill437fa652016-05-03 15:13:24 -04003585 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003586 return false;
3587 }
3588
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003589 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003590
3591 if (!buffer)
3592 {
Jamie Madill437fa652016-05-03 15:13:24 -04003593 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003594 return false;
3595 }
3596
3597 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003598 CheckedNumeric<size_t> checkedOffset(offset);
3599 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003600
Jamie Madille2e406c2016-06-02 13:04:10 -04003601 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003602 {
Jamie Madill437fa652016-05-03 15:13:24 -04003603 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003604 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
3605 return false;
3606 }
3607
3608 // Check for invalid bits in the mask
3609 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3610 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3611 GL_MAP_UNSYNCHRONIZED_BIT;
3612
3613 if (access & ~(allAccessBits))
3614 {
Jamie Madill437fa652016-05-03 15:13:24 -04003615 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03003616 return false;
3617 }
3618
3619 if (length == 0)
3620 {
Jamie Madill437fa652016-05-03 15:13:24 -04003621 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003622 return false;
3623 }
3624
3625 if (buffer->isMapped())
3626 {
Jamie Madill437fa652016-05-03 15:13:24 -04003627 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003628 return false;
3629 }
3630
3631 // Check for invalid bit combinations
3632 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3633 {
Jamie Madill437fa652016-05-03 15:13:24 -04003634 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003635 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
3636 return false;
3637 }
3638
3639 GLbitfield writeOnlyBits =
3640 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3641
3642 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3643 {
Jamie Madill437fa652016-05-03 15:13:24 -04003644 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03003645 "Invalid access bits when mapping buffer for reading: 0x%X.",
3646 access));
3647 return false;
3648 }
3649
3650 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3651 {
Jamie Madill437fa652016-05-03 15:13:24 -04003652 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003653 GL_INVALID_OPERATION,
3654 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
3655 return false;
3656 }
3657 return true;
3658}
3659
3660bool ValidateFlushMappedBufferRangeBase(Context *context,
3661 GLenum target,
3662 GLintptr offset,
3663 GLsizeiptr length)
3664{
3665 if (offset < 0 || length < 0)
3666 {
Jamie Madill437fa652016-05-03 15:13:24 -04003667 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003668 return false;
3669 }
3670
3671 if (!ValidBufferTarget(context, target))
3672 {
Jamie Madill437fa652016-05-03 15:13:24 -04003673 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003674 return false;
3675 }
3676
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003677 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003678
3679 if (buffer == nullptr)
3680 {
Jamie Madill437fa652016-05-03 15:13:24 -04003681 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003682 return false;
3683 }
3684
3685 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3686 {
Jamie Madill437fa652016-05-03 15:13:24 -04003687 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003688 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
3689 return false;
3690 }
3691
3692 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003693 CheckedNumeric<size_t> checkedOffset(offset);
3694 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003695
Jamie Madille2e406c2016-06-02 13:04:10 -04003696 if (!checkedSize.IsValid() ||
3697 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003698 {
Jamie Madill437fa652016-05-03 15:13:24 -04003699 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003700 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
3701 return false;
3702 }
3703
3704 return true;
3705}
3706
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003707bool ValidateGenerateMipmap(Context *context, GLenum target)
3708{
3709 if (!ValidTextureTarget(context, target))
3710 {
3711 context->handleError(Error(GL_INVALID_ENUM));
3712 return false;
3713 }
3714
3715 Texture *texture = context->getTargetTexture(target);
3716
3717 if (texture == nullptr)
3718 {
3719 context->handleError(Error(GL_INVALID_OPERATION));
3720 return false;
3721 }
3722
3723 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
3724
3725 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
3726 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
3727 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
3728 {
3729 context->handleError(Error(GL_INVALID_OPERATION));
3730 return false;
3731 }
3732
Jamie Madilla3944d42016-07-22 22:13:26 -04003733 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
3734 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
3735 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003736
3737 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
3738 // unsized formats or that are color renderable and filterable. Since we do not track if
3739 // the texture was created with sized or unsized format (only sized formats are stored),
3740 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
3741 // be able to) because they aren't color renderable. Simply do a special case for LUMA
3742 // textures since they're the only texture format that can be created with unsized formats
3743 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
3744 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04003745 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
3746 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003747 {
3748 context->handleError(Error(GL_INVALID_OPERATION));
3749 return false;
3750 }
3751
3752 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04003753 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003754 {
3755 context->handleError(Error(GL_INVALID_OPERATION));
3756 return false;
3757 }
3758
3759 // Non-power of 2 ES2 check
3760 if (!context->getExtensions().textureNPOT &&
3761 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
3762 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
3763 {
Martin Radev1be913c2016-07-11 17:59:16 +03003764 ASSERT(context->getClientMajorVersion() <= 2 &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003765 (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
3766 context->handleError(Error(GL_INVALID_OPERATION));
3767 return false;
3768 }
3769
3770 // Cube completeness check
3771 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
3772 {
3773 context->handleError(Error(GL_INVALID_OPERATION));
3774 return false;
3775 }
3776
3777 return true;
3778}
3779
Olli Etuaho41997e72016-03-10 13:38:39 +02003780bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
3781{
3782 return ValidateGenOrDelete(context, n);
3783}
3784
3785bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
3786{
3787 return ValidateGenOrDelete(context, n);
3788}
3789
3790bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
3791{
3792 return ValidateGenOrDelete(context, n);
3793}
3794
3795bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
3796{
3797 return ValidateGenOrDelete(context, n);
3798}
3799
3800bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
3801{
3802 return ValidateGenOrDelete(context, n);
3803}
3804
3805bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
3806{
3807 return ValidateGenOrDelete(context, n);
3808}
3809
3810bool ValidateGenTextures(Context *context, GLint n, GLuint *)
3811{
3812 return ValidateGenOrDelete(context, n);
3813}
3814
3815bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
3816{
3817 return ValidateGenOrDelete(context, n);
3818}
3819
3820bool ValidateGenOrDelete(Context *context, GLint n)
3821{
3822 if (n < 0)
3823 {
Jamie Madill437fa652016-05-03 15:13:24 -04003824 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02003825 return false;
3826 }
3827 return true;
3828}
3829
Geoff Langf41a7152016-09-19 15:11:17 -04003830bool ValidateEnable(Context *context, GLenum cap)
3831{
3832 if (!ValidCap(context, cap, false))
3833 {
3834 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3835 return false;
3836 }
3837
3838 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
3839 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
3840 {
3841 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
3842 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
3843
3844 // We also output an error message to the debugger window if tracing is active, so that
3845 // developers can see the error message.
3846 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04003847 return false;
3848 }
3849
3850 return true;
3851}
3852
3853bool ValidateDisable(Context *context, GLenum cap)
3854{
3855 if (!ValidCap(context, cap, false))
3856 {
3857 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3858 return false;
3859 }
3860
3861 return true;
3862}
3863
3864bool ValidateIsEnabled(Context *context, GLenum cap)
3865{
3866 if (!ValidCap(context, cap, true))
3867 {
3868 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
3869 return false;
3870 }
3871
3872 return true;
3873}
3874
Geoff Langff5b2d52016-09-07 11:32:23 -04003875bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3876{
3877 if (!context->getExtensions().robustClientMemory)
3878 {
3879 context->handleError(
3880 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
3881 return false;
3882 }
3883
3884 if (bufSize < 0)
3885 {
3886 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3887 return false;
3888 }
3889
3890 return true;
3891}
3892
3893bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
3894 GLenum target,
3895 GLenum attachment,
3896 GLenum pname,
3897 GLsizei *numParams)
3898{
3899 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
3900 *numParams = 1;
3901
3902 if (!ValidFramebufferTarget(target))
3903 {
3904 context->handleError(Error(GL_INVALID_ENUM));
3905 return false;
3906 }
3907
3908 int clientVersion = context->getClientMajorVersion();
3909
3910 switch (pname)
3911 {
3912 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3913 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3914 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3915 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3916 break;
3917
3918 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3919 if (clientVersion < 3 && !context->getExtensions().sRGB)
3920 {
3921 context->handleError(Error(GL_INVALID_ENUM));
3922 return false;
3923 }
3924 break;
3925
3926 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3927 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3928 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3929 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3930 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3931 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3932 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3933 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3934 if (clientVersion < 3)
3935 {
3936 context->handleError(Error(GL_INVALID_ENUM));
3937 return false;
3938 }
3939 break;
3940
3941 default:
3942 context->handleError(Error(GL_INVALID_ENUM));
3943 return false;
3944 }
3945
3946 // Determine if the attachment is a valid enum
3947 switch (attachment)
3948 {
3949 case GL_BACK:
3950 case GL_FRONT:
3951 case GL_DEPTH:
3952 case GL_STENCIL:
3953 case GL_DEPTH_STENCIL_ATTACHMENT:
3954 if (clientVersion < 3)
3955 {
3956 context->handleError(Error(GL_INVALID_ENUM));
3957 return false;
3958 }
3959 break;
3960
3961 case GL_DEPTH_ATTACHMENT:
3962 case GL_STENCIL_ATTACHMENT:
3963 break;
3964
3965 default:
3966 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3967 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3968 {
3969 context->handleError(Error(GL_INVALID_ENUM));
3970 return false;
3971 }
3972 break;
3973 }
3974
3975 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3976 ASSERT(framebuffer);
3977
3978 if (framebuffer->id() == 0)
3979 {
3980 if (clientVersion < 3)
3981 {
3982 context->handleError(Error(GL_INVALID_OPERATION));
3983 return false;
3984 }
3985
3986 switch (attachment)
3987 {
3988 case GL_BACK:
3989 case GL_DEPTH:
3990 case GL_STENCIL:
3991 break;
3992
3993 default:
3994 context->handleError(Error(GL_INVALID_OPERATION));
3995 return false;
3996 }
3997 }
3998 else
3999 {
4000 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4001 {
4002 // Valid attachment query
4003 }
4004 else
4005 {
4006 switch (attachment)
4007 {
4008 case GL_DEPTH_ATTACHMENT:
4009 case GL_STENCIL_ATTACHMENT:
4010 break;
4011
4012 case GL_DEPTH_STENCIL_ATTACHMENT:
4013 if (!framebuffer->hasValidDepthStencil())
4014 {
4015 context->handleError(Error(GL_INVALID_OPERATION));
4016 return false;
4017 }
4018 break;
4019
4020 default:
4021 context->handleError(Error(GL_INVALID_OPERATION));
4022 return false;
4023 }
4024 }
4025 }
4026
4027 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4028 if (attachmentObject)
4029 {
4030 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4031 attachmentObject->type() == GL_TEXTURE ||
4032 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4033
4034 switch (pname)
4035 {
4036 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4037 if (attachmentObject->type() != GL_RENDERBUFFER &&
4038 attachmentObject->type() != GL_TEXTURE)
4039 {
4040 context->handleError(Error(GL_INVALID_ENUM));
4041 return false;
4042 }
4043 break;
4044
4045 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4046 if (attachmentObject->type() != GL_TEXTURE)
4047 {
4048 context->handleError(Error(GL_INVALID_ENUM));
4049 return false;
4050 }
4051 break;
4052
4053 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4054 if (attachmentObject->type() != GL_TEXTURE)
4055 {
4056 context->handleError(Error(GL_INVALID_ENUM));
4057 return false;
4058 }
4059 break;
4060
4061 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4062 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4063 {
4064 context->handleError(Error(GL_INVALID_OPERATION));
4065 return false;
4066 }
4067 break;
4068
4069 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4070 if (attachmentObject->type() != GL_TEXTURE)
4071 {
4072 context->handleError(Error(GL_INVALID_ENUM));
4073 return false;
4074 }
4075 break;
4076
4077 default:
4078 break;
4079 }
4080 }
4081 else
4082 {
4083 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4084 // is NONE, then querying any other pname will generate INVALID_ENUM.
4085
4086 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4087 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4088 // INVALID_OPERATION for all other pnames
4089
4090 switch (pname)
4091 {
4092 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4093 break;
4094
4095 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4096 if (clientVersion < 3)
4097 {
4098 context->handleError(Error(GL_INVALID_ENUM));
4099 return false;
4100 }
4101 break;
4102
4103 default:
4104 if (clientVersion < 3)
4105 {
4106 context->handleError(Error(GL_INVALID_ENUM));
4107 return false;
4108 }
4109 else
4110 {
4111 context->handleError(Error(GL_INVALID_OPERATION));
4112 return false;
4113 }
4114 }
4115 }
4116
4117 return true;
4118}
4119
4120bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4121 GLenum target,
4122 GLenum attachment,
4123 GLenum pname,
4124 GLsizei bufSize,
4125 GLsizei *numParams)
4126{
4127 if (!ValidateRobustEntryPoint(context, bufSize))
4128 {
4129 return false;
4130 }
4131
4132 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4133 {
4134 return false;
4135 }
4136
4137 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4138 {
4139 return false;
4140 }
4141
4142 return true;
4143}
4144
4145bool ValidateGetBufferParameteriv(ValidationContext *context,
4146 GLenum target,
4147 GLenum pname,
4148 GLsizei *numParams)
4149{
4150 // Initialize result
4151 *numParams = 0;
4152
4153 if (!ValidBufferTarget(context, target))
4154 {
4155 context->handleError(Error(GL_INVALID_ENUM));
4156 return false;
4157 }
4158
4159 if (!ValidBufferParameter(context, pname, numParams))
4160 {
4161 context->handleError(Error(GL_INVALID_ENUM));
4162 return false;
4163 }
4164
4165 if (context->getGLState().getTargetBuffer(target) == nullptr)
4166 {
4167 // A null buffer means that "0" is bound to the requested buffer target
4168 context->handleError(Error(GL_INVALID_OPERATION));
4169 return false;
4170 }
4171
4172 return true;
4173}
4174
4175bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4176 GLenum target,
4177 GLenum pname,
4178 GLsizei bufSize,
4179 GLsizei *numParams)
4180{
4181 if (!ValidateRobustEntryPoint(context, bufSize))
4182 {
4183 return false;
4184 }
4185
4186 if (!ValidateGetBufferParameteriv(context, target, pname, numParams))
4187 {
4188 return false;
4189 }
4190
4191 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4192 {
4193 return false;
4194 }
4195
4196 return true;
4197}
4198
4199bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4200{
4201 // Currently, all GetProgramiv queries return 1 parameter
4202 *numParams = 1;
4203
4204 Program *programObject = GetValidProgram(context, program);
4205 if (!programObject)
4206 {
4207 return false;
4208 }
4209
4210 switch (pname)
4211 {
4212 case GL_DELETE_STATUS:
4213 case GL_LINK_STATUS:
4214 case GL_VALIDATE_STATUS:
4215 case GL_INFO_LOG_LENGTH:
4216 case GL_ATTACHED_SHADERS:
4217 case GL_ACTIVE_ATTRIBUTES:
4218 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4219 case GL_ACTIVE_UNIFORMS:
4220 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4221 break;
4222
4223 case GL_PROGRAM_BINARY_LENGTH:
4224 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4225 {
4226 context->handleError(Error(GL_INVALID_ENUM,
4227 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4228 "GL_OES_get_program_binary or ES 3.0."));
4229 return false;
4230 }
4231 break;
4232
4233 case GL_ACTIVE_UNIFORM_BLOCKS:
4234 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4235 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4236 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4237 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4238 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4239 if (context->getClientMajorVersion() < 3)
4240 {
4241 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4242 return false;
4243 }
4244 break;
4245
4246 default:
4247 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4248 return false;
4249 }
4250
4251 return true;
4252}
4253
4254bool ValidateGetProgramivRobustANGLE(Context *context,
4255 GLuint program,
4256 GLenum pname,
4257 GLsizei bufSize,
4258 GLsizei *numParams)
4259{
4260 if (!ValidateRobustEntryPoint(context, bufSize))
4261 {
4262 return false;
4263 }
4264
4265 if (!ValidateGetProgramiv(context, program, pname, numParams))
4266 {
4267 return false;
4268 }
4269
4270 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4271 {
4272 return false;
4273 }
4274
4275 return true;
4276}
4277
Geoff Lang740d9022016-10-07 11:20:52 -04004278bool ValidateGetRenderbufferParameteriv(Context *context,
4279 GLenum target,
4280 GLenum pname,
4281 GLint *params)
4282{
4283 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4284}
4285
4286bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4287 GLenum target,
4288 GLenum pname,
4289 GLsizei bufSize,
4290 GLsizei *length,
4291 GLint *params)
4292{
4293 if (!ValidateRobustEntryPoint(context, bufSize))
4294 {
4295 return false;
4296 }
4297
4298 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4299 {
4300 return false;
4301 }
4302
4303 if (!ValidateRobustBufferSize(context, bufSize, *length))
4304 {
4305 return false;
4306 }
4307
4308 return true;
4309}
4310
Geoff Langd7d0ed32016-10-07 11:33:51 -04004311bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
4312{
4313 return ValidateGetShaderivBase(context, shader, pname, nullptr);
4314}
4315
4316bool ValidateGetShaderivRobustANGLE(Context *context,
4317 GLuint shader,
4318 GLenum pname,
4319 GLsizei bufSize,
4320 GLsizei *length,
4321 GLint *params)
4322{
4323 if (!ValidateRobustEntryPoint(context, bufSize))
4324 {
4325 return false;
4326 }
4327
4328 if (!ValidateGetShaderivBase(context, shader, pname, length))
4329 {
4330 return false;
4331 }
4332
4333 if (!ValidateRobustBufferSize(context, bufSize, *length))
4334 {
4335 return false;
4336 }
4337
4338 return true;
4339}
4340
Geoff Langc1984ed2016-10-07 12:41:00 -04004341bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
4342{
4343 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4344}
4345
4346bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4347 GLenum target,
4348 GLenum pname,
4349 GLsizei bufSize,
4350 GLsizei *length,
4351 GLfloat *params)
4352{
4353 if (!ValidateRobustEntryPoint(context, bufSize))
4354 {
4355 return false;
4356 }
4357
4358 if (!ValidateGetTexParameterBase(context, target, pname, length))
4359 {
4360 return false;
4361 }
4362
4363 if (!ValidateRobustBufferSize(context, bufSize, *length))
4364 {
4365 return false;
4366 }
4367
4368 return true;
4369}
4370
4371bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
4372{
4373 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4374}
4375
4376bool ValidateGetTexParameterivRobustANGLE(Context *context,
4377 GLenum target,
4378 GLenum pname,
4379 GLsizei bufSize,
4380 GLsizei *length,
4381 GLint *params)
4382{
4383 if (!ValidateRobustEntryPoint(context, bufSize))
4384 {
4385 return false;
4386 }
4387
4388 if (!ValidateGetTexParameterBase(context, target, pname, length))
4389 {
4390 return false;
4391 }
4392
4393 if (!ValidateRobustBufferSize(context, bufSize, *length))
4394 {
4395 return false;
4396 }
4397
4398 return true;
4399}
4400
4401bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
4402{
4403 return ValidateTexParameterBase(context, target, pname, -1, &param);
4404}
4405
4406bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
4407{
4408 return ValidateTexParameterBase(context, target, pname, -1, params);
4409}
4410
4411bool ValidateTexParameterfvRobustANGLE(Context *context,
4412 GLenum target,
4413 GLenum pname,
4414 GLsizei bufSize,
4415 const GLfloat *params)
4416{
4417 if (!ValidateRobustEntryPoint(context, bufSize))
4418 {
4419 return false;
4420 }
4421
4422 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4423}
4424
4425bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
4426{
4427 return ValidateTexParameterBase(context, target, pname, -1, &param);
4428}
4429
4430bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
4431{
4432 return ValidateTexParameterBase(context, target, pname, -1, params);
4433}
4434
4435bool ValidateTexParameterivRobustANGLE(Context *context,
4436 GLenum target,
4437 GLenum pname,
4438 GLsizei bufSize,
4439 const GLint *params)
4440{
4441 if (!ValidateRobustEntryPoint(context, bufSize))
4442 {
4443 return false;
4444 }
4445
4446 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4447}
4448
4449bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4450{
4451 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4452}
4453
4454bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4455 GLuint sampler,
4456 GLenum pname,
4457 GLuint bufSize,
4458 GLsizei *length,
4459 GLfloat *params)
4460{
4461 if (!ValidateRobustEntryPoint(context, bufSize))
4462 {
4463 return false;
4464 }
4465
4466 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4467 {
4468 return false;
4469 }
4470
4471 if (!ValidateRobustBufferSize(context, bufSize, *length))
4472 {
4473 return false;
4474 }
4475
4476 return true;
4477}
4478
4479bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4480{
4481 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4482}
4483
4484bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4485 GLuint sampler,
4486 GLenum pname,
4487 GLuint bufSize,
4488 GLsizei *length,
4489 GLint *params)
4490{
4491 if (!ValidateRobustEntryPoint(context, bufSize))
4492 {
4493 return false;
4494 }
4495
4496 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4497 {
4498 return false;
4499 }
4500
4501 if (!ValidateRobustBufferSize(context, bufSize, *length))
4502 {
4503 return false;
4504 }
4505
4506 return true;
4507}
4508
4509bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4510{
4511 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4512}
4513
4514bool ValidateSamplerParameterfv(Context *context,
4515 GLuint sampler,
4516 GLenum pname,
4517 const GLfloat *params)
4518{
4519 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4520}
4521
4522bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4523 GLuint sampler,
4524 GLenum pname,
4525 GLsizei bufSize,
4526 const GLfloat *params)
4527{
4528 if (!ValidateRobustEntryPoint(context, bufSize))
4529 {
4530 return false;
4531 }
4532
4533 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4534}
4535
4536bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4537{
4538 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4539}
4540
4541bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4542{
4543 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4544}
4545
4546bool ValidateSamplerParameterivRobustANGLE(Context *context,
4547 GLuint sampler,
4548 GLenum pname,
4549 GLsizei bufSize,
4550 const GLint *params)
4551{
4552 if (!ValidateRobustEntryPoint(context, bufSize))
4553 {
4554 return false;
4555 }
4556
4557 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4558}
4559
Jamie Madillc29968b2016-01-20 11:17:23 -05004560} // namespace gl