blob: 9c96f78996a1eab548fa40495fbd96c7e79db4ee [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES2.h"
12#include "libANGLE/validationES3.h"
13#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040014#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Texture.h"
16#include "libANGLE/Framebuffer.h"
17#include "libANGLE/FramebufferAttachment.h"
18#include "libANGLE/formatutils.h"
Geoff Langa8406172015-07-21 16:53:39 -040019#include "libANGLE/Image.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/Query.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050021#include "libANGLE/Program.h"
22#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/TransformFeedback.h"
24#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025
26#include "common/mathutil.h"
27#include "common/utilities.h"
28
Jamie Madille2e406c2016-06-02 13:04:10 -040029using namespace angle;
30
Geoff Lange8ebe7f2013-08-05 15:03:13 -040031namespace gl
32{
Jamie Madille79b1e12015-11-04 16:36:37 -050033const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
34
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Jamie Madillf25855c2015-11-03 11:06:18 -050037bool ValidateDrawAttribs(ValidationContext *context, GLint primcount, GLint maxVertex)
Jamie Madill1ca74672015-07-21 15:14:11 -040038{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070039 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040040 const gl::Program *program = state.getProgram();
41
42 const VertexArray *vao = state.getVertexArray();
43 const auto &vertexAttribs = vao->getVertexAttributes();
Jamie Madill1ca74672015-07-21 15:14:11 -040044 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
45 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
46 {
47 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill63805b42015-08-25 13:17:39 -040048 if (program->isAttribLocationActive(attributeIndex) && attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040049 {
50 gl::Buffer *buffer = attrib.buffer.get();
51
52 if (buffer)
53 {
54 GLint64 attribStride = static_cast<GLint64>(ComputeVertexAttributeStride(attrib));
55 GLint64 maxVertexElement = 0;
56
57 if (attrib.divisor > 0)
58 {
59 maxVertexElement =
60 static_cast<GLint64>(primcount) / static_cast<GLint64>(attrib.divisor);
61 }
62 else
63 {
64 maxVertexElement = static_cast<GLint64>(maxVertex);
65 }
66
67 // If we're drawing zero vertices, we have enough data.
68 if (maxVertexElement > 0)
69 {
70 // Note: Last vertex element does not take the full stride!
71 GLint64 attribSize =
72 static_cast<GLint64>(ComputeVertexAttributeTypeSize(attrib));
73 GLint64 attribDataSize = (maxVertexElement - 1) * attribStride + attribSize;
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040074 GLint64 attribOffset = static_cast<GLint64>(attrib.offset);
Jamie Madill1ca74672015-07-21 15:14:11 -040075
76 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
77 // We can return INVALID_OPERATION if our vertex attribute does not have
78 // enough backing data.
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040079 if (attribDataSize + attribOffset > buffer->getSize())
Jamie Madill1ca74672015-07-21 15:14:11 -040080 {
Jamie Madill437fa652016-05-03 15:13:24 -040081 context->handleError(
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040082 Error(GL_INVALID_OPERATION,
83 "Vertex buffer is not big enough for the draw call"));
Jamie Madill1ca74672015-07-21 15:14:11 -040084 return false;
85 }
86 }
87 }
88 else if (attrib.pointer == NULL)
89 {
90 // This is an application error that would normally result in a crash,
91 // but we catch it and return an error
Jamie Madill437fa652016-05-03 15:13:24 -040092 context->handleError(Error(
Jamie Madill1ca74672015-07-21 15:14:11 -040093 GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
94 return false;
95 }
96 }
97 }
98
99 return true;
100}
101
Geoff Langf607c602016-09-21 11:46:48 -0400102bool ValidReadPixelsFormatType(ValidationContext *context,
103 GLenum framebufferComponentType,
104 GLenum format,
105 GLenum type)
106{
107 switch (framebufferComponentType)
108 {
109 case GL_UNSIGNED_NORMALIZED:
110 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
111 // ReadPixels with BGRA even if the extension is not present
112 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
113 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
114 type == GL_UNSIGNED_BYTE);
115
116 case GL_SIGNED_NORMALIZED:
117 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
118
119 case GL_INT:
120 return (format == GL_RGBA_INTEGER && type == GL_INT);
121
122 case GL_UNSIGNED_INT:
123 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
124
125 case GL_FLOAT:
126 return (format == GL_RGBA && type == GL_FLOAT);
127
128 default:
129 UNREACHABLE();
130 return false;
131 }
132}
133
Geoff Langf41a7152016-09-19 15:11:17 -0400134bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500135{
136 switch (cap)
137 {
Geoff Langf41a7152016-09-19 15:11:17 -0400138 // EXT_multisample_compatibility
139 case GL_MULTISAMPLE_EXT:
140 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
141 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300142
Geoff Langf41a7152016-09-19 15:11:17 -0400143 case GL_CULL_FACE:
144 case GL_POLYGON_OFFSET_FILL:
145 case GL_SAMPLE_ALPHA_TO_COVERAGE:
146 case GL_SAMPLE_COVERAGE:
147 case GL_SCISSOR_TEST:
148 case GL_STENCIL_TEST:
149 case GL_DEPTH_TEST:
150 case GL_BLEND:
151 case GL_DITHER:
152 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500153
Geoff Langf41a7152016-09-19 15:11:17 -0400154 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
155 case GL_RASTERIZER_DISCARD:
156 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500157
Geoff Langf41a7152016-09-19 15:11:17 -0400158 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
159 case GL_DEBUG_OUTPUT:
160 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500161
Geoff Langf41a7152016-09-19 15:11:17 -0400162 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
163 return queryOnly && context->getExtensions().bindGeneratesResource;
164
165 default:
166 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500167 }
168}
169
Geoff Lang62fce5b2016-09-30 10:46:35 -0400170bool ValidateReadPixelsBase(ValidationContext *context,
171 GLint x,
172 GLint y,
173 GLsizei width,
174 GLsizei height,
175 GLenum format,
176 GLenum type,
177 GLsizei bufSize,
178 GLsizei *length,
179 GLvoid *pixels)
180{
181 if (length != nullptr)
182 {
183 *length = 0;
184 }
185
186 if (width < 0 || height < 0)
187 {
188 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
189 return false;
190 }
191
192 auto readFramebuffer = context->getGLState().getReadFramebuffer();
193
194 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
195 {
196 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
197 return false;
198 }
199
200 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
201 {
202 context->handleError(Error(GL_INVALID_OPERATION));
203 return false;
204 }
205
206 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
207 ASSERT(framebuffer);
208
209 if (framebuffer->getReadBufferState() == GL_NONE)
210 {
211 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
212 return false;
213 }
214
215 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
216 if (!readBuffer)
217 {
218 context->handleError(Error(GL_INVALID_OPERATION));
219 return false;
220 }
221
222 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
223 GLenum currentType = framebuffer->getImplementationColorReadType();
224 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
225
226 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
227 bool validFormatTypeCombination =
228 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
229
230 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
231 {
232 context->handleError(Error(GL_INVALID_OPERATION));
233 return false;
234 }
235
236 // Check for pixel pack buffer related API errors
237 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
238 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
239 {
240 // ...the buffer object's data store is currently mapped.
241 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
242 return false;
243 }
244
245 // .. the data would be packed to the buffer object such that the memory writes required
246 // would exceed the data store size.
247 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
248 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
249 const gl::Extents size(width, height, 1);
250 const auto &pack = context->getGLState().getPackState();
251
252 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
253 if (endByteOrErr.isError())
254 {
255 context->handleError(endByteOrErr.getError());
256 return false;
257 }
258
259 size_t endByte = endByteOrErr.getResult();
260 if (bufSize >= 0)
261 {
262
263 if (static_cast<size_t>(bufSize) < endByte)
264 {
265 context->handleError(
266 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
267 return false;
268 }
269 }
270
271 if (pixelPackBuffer != nullptr)
272 {
273 CheckedNumeric<size_t> checkedEndByte(endByte);
274 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
275 checkedEndByte += checkedOffset;
276
277 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
278 {
279 // Overflow past the end of the buffer
280 context->handleError(
281 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
282 return false;
283 }
284 }
285
286 if (length != nullptr)
287 {
288 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
289 {
290 context->handleError(
291 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
292 return false;
293 }
294
295 *length = static_cast<GLsizei>(endByte);
296 }
297
298 return true;
299}
300
Geoff Lang740d9022016-10-07 11:20:52 -0400301bool ValidateGetRenderbufferParameterivBase(Context *context,
302 GLenum target,
303 GLenum pname,
304 GLsizei *length)
305{
306 if (length)
307 {
308 *length = 0;
309 }
310
311 if (target != GL_RENDERBUFFER)
312 {
313 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
314 return false;
315 }
316
317 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
318 if (renderbuffer == nullptr)
319 {
320 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
321 return false;
322 }
323
324 switch (pname)
325 {
326 case GL_RENDERBUFFER_WIDTH:
327 case GL_RENDERBUFFER_HEIGHT:
328 case GL_RENDERBUFFER_INTERNAL_FORMAT:
329 case GL_RENDERBUFFER_RED_SIZE:
330 case GL_RENDERBUFFER_GREEN_SIZE:
331 case GL_RENDERBUFFER_BLUE_SIZE:
332 case GL_RENDERBUFFER_ALPHA_SIZE:
333 case GL_RENDERBUFFER_DEPTH_SIZE:
334 case GL_RENDERBUFFER_STENCIL_SIZE:
335 break;
336
337 case GL_RENDERBUFFER_SAMPLES_ANGLE:
338 if (!context->getExtensions().framebufferMultisample)
339 {
340 context->handleError(
341 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
342 return false;
343 }
344 break;
345
346 default:
347 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
348 return false;
349 }
350
351 if (length)
352 {
353 *length = 1;
354 }
355 return true;
356}
357
Geoff Langd7d0ed32016-10-07 11:33:51 -0400358bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
359{
360 if (length)
361 {
362 *length = 0;
363 }
364
365 if (GetValidShader(context, shader) == nullptr)
366 {
367 return false;
368 }
369
370 switch (pname)
371 {
372 case GL_SHADER_TYPE:
373 case GL_DELETE_STATUS:
374 case GL_COMPILE_STATUS:
375 case GL_INFO_LOG_LENGTH:
376 case GL_SHADER_SOURCE_LENGTH:
377 break;
378
379 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
380 if (!context->getExtensions().translatedShaderSource)
381 {
382 context->handleError(
383 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
384 return false;
385 }
386 break;
387
388 default:
389 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
390 return false;
391 }
392
393 if (length)
394 {
395 *length = 1;
396 }
397 return true;
398}
399
Geoff Langc1984ed2016-10-07 12:41:00 -0400400bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
401{
402 if (length)
403 {
404 *length = 0;
405 }
406
407 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
408 {
409 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
410 return false;
411 }
412
413 if (context->getTargetTexture(target) == nullptr)
414 {
415 // Should only be possible for external textures
416 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
417 return false;
418 }
419
420 switch (pname)
421 {
422 case GL_TEXTURE_MAG_FILTER:
423 case GL_TEXTURE_MIN_FILTER:
424 case GL_TEXTURE_WRAP_S:
425 case GL_TEXTURE_WRAP_T:
426 break;
427
428 case GL_TEXTURE_USAGE_ANGLE:
429 if (!context->getExtensions().textureUsage)
430 {
431 context->handleError(
432 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
433 return false;
434 }
435 break;
436
437 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
438 if (!context->getExtensions().textureFilterAnisotropic)
439 {
440 context->handleError(
441 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
442 return false;
443 }
444 break;
445
446 case GL_TEXTURE_IMMUTABLE_FORMAT:
447 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
448 {
449 context->handleError(
450 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
451 return false;
452 }
453 break;
454
455 case GL_TEXTURE_WRAP_R:
456 case GL_TEXTURE_IMMUTABLE_LEVELS:
457 case GL_TEXTURE_SWIZZLE_R:
458 case GL_TEXTURE_SWIZZLE_G:
459 case GL_TEXTURE_SWIZZLE_B:
460 case GL_TEXTURE_SWIZZLE_A:
461 case GL_TEXTURE_BASE_LEVEL:
462 case GL_TEXTURE_MAX_LEVEL:
463 case GL_TEXTURE_MIN_LOD:
464 case GL_TEXTURE_MAX_LOD:
465 case GL_TEXTURE_COMPARE_MODE:
466 case GL_TEXTURE_COMPARE_FUNC:
467 if (context->getClientMajorVersion() < 3)
468 {
469 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
470 return false;
471 }
472 break;
473
474 default:
475 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
476 return false;
477 }
478
479 if (length)
480 {
481 *length = 1;
482 }
483 return true;
484}
485
486template <typename ParamType>
487bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
488{
489 switch (ConvertToGLenum(params[0]))
490 {
491 case GL_CLAMP_TO_EDGE:
492 break;
493
494 case GL_REPEAT:
495 case GL_MIRRORED_REPEAT:
496 if (isExternalTextureTarget)
497 {
498 // OES_EGL_image_external specifies this error.
499 context->handleError(Error(
500 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
501 return false;
502 }
503 break;
504
505 default:
506 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
507 return false;
508 }
509
510 return true;
511}
512
513template <typename ParamType>
514bool ValidateTextureMinFilterValue(Context *context,
515 ParamType *params,
516 bool isExternalTextureTarget)
517{
518 switch (ConvertToGLenum(params[0]))
519 {
520 case GL_NEAREST:
521 case GL_LINEAR:
522 break;
523
524 case GL_NEAREST_MIPMAP_NEAREST:
525 case GL_LINEAR_MIPMAP_NEAREST:
526 case GL_NEAREST_MIPMAP_LINEAR:
527 case GL_LINEAR_MIPMAP_LINEAR:
528 if (isExternalTextureTarget)
529 {
530 // OES_EGL_image_external specifies this error.
531 context->handleError(
532 Error(GL_INVALID_ENUM,
533 "external textures only support NEAREST and LINEAR filtering"));
534 return false;
535 }
536 break;
537
538 default:
539 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
540 return false;
541 }
542
543 return true;
544}
545
546template <typename ParamType>
547bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
548{
549 switch (ConvertToGLenum(params[0]))
550 {
551 case GL_NEAREST:
552 case GL_LINEAR:
553 break;
554
555 default:
556 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
557 return false;
558 }
559
560 return true;
561}
562
563template <typename ParamType>
564bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
565{
566 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
567 switch (ConvertToGLenum(params[0]))
568 {
569 case GL_NONE:
570 case GL_COMPARE_REF_TO_TEXTURE:
571 break;
572
573 default:
574 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
575 return false;
576 }
577
578 return true;
579}
580
581template <typename ParamType>
582bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
583{
584 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
585 switch (ConvertToGLenum(params[0]))
586 {
587 case GL_LEQUAL:
588 case GL_GEQUAL:
589 case GL_LESS:
590 case GL_GREATER:
591 case GL_EQUAL:
592 case GL_NOTEQUAL:
593 case GL_ALWAYS:
594 case GL_NEVER:
595 break;
596
597 default:
598 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
599 return false;
600 }
601
602 return true;
603}
604
605template <typename ParamType>
606bool ValidateTexParameterBase(Context *context,
607 GLenum target,
608 GLenum pname,
609 GLsizei bufSize,
610 ParamType *params)
611{
612 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
613 {
614 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
615 return false;
616 }
617
618 if (context->getTargetTexture(target) == nullptr)
619 {
620 // Should only be possible for external textures
621 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
622 return false;
623 }
624
625 const GLsizei minBufSize = 1;
626 if (bufSize >= 0 && bufSize < minBufSize)
627 {
628 context->handleError(
629 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
630 return false;
631 }
632
633 switch (pname)
634 {
635 case GL_TEXTURE_WRAP_R:
636 case GL_TEXTURE_SWIZZLE_R:
637 case GL_TEXTURE_SWIZZLE_G:
638 case GL_TEXTURE_SWIZZLE_B:
639 case GL_TEXTURE_SWIZZLE_A:
640 case GL_TEXTURE_BASE_LEVEL:
641 case GL_TEXTURE_MAX_LEVEL:
642 case GL_TEXTURE_COMPARE_MODE:
643 case GL_TEXTURE_COMPARE_FUNC:
644 case GL_TEXTURE_MIN_LOD:
645 case GL_TEXTURE_MAX_LOD:
646 if (context->getClientMajorVersion() < 3)
647 {
648 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
649 return false;
650 }
651 if (target == GL_TEXTURE_EXTERNAL_OES &&
652 !context->getExtensions().eglImageExternalEssl3)
653 {
654 context->handleError(Error(GL_INVALID_ENUM,
655 "ES3 texture parameters are not available without "
656 "GL_OES_EGL_image_external_essl3."));
657 return false;
658 }
659 break;
660
661 default:
662 break;
663 }
664
665 switch (pname)
666 {
667 case GL_TEXTURE_WRAP_S:
668 case GL_TEXTURE_WRAP_T:
669 case GL_TEXTURE_WRAP_R:
670 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
671 {
672 return false;
673 }
674 break;
675
676 case GL_TEXTURE_MIN_FILTER:
677 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
678 {
679 return false;
680 }
681 break;
682
683 case GL_TEXTURE_MAG_FILTER:
684 if (!ValidateTextureMagFilterValue(context, params))
685 {
686 return false;
687 }
688 break;
689
690 case GL_TEXTURE_USAGE_ANGLE:
691 switch (ConvertToGLenum(params[0]))
692 {
693 case GL_NONE:
694 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
695 break;
696
697 default:
698 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
699 return false;
700 }
701 break;
702
703 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
704 if (!context->getExtensions().textureFilterAnisotropic)
705 {
706 context->handleError(
707 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
708 return false;
709 }
710
711 // we assume the parameter passed to this validation method is truncated, not rounded
712 if (params[0] < 1)
713 {
714 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
715 return false;
716 }
717 break;
718
719 case GL_TEXTURE_MIN_LOD:
720 case GL_TEXTURE_MAX_LOD:
721 // any value is permissible
722 break;
723
724 case GL_TEXTURE_COMPARE_MODE:
725 if (!ValidateTextureCompareModeValue(context, params))
726 {
727 return false;
728 }
729 break;
730
731 case GL_TEXTURE_COMPARE_FUNC:
732 if (!ValidateTextureCompareFuncValue(context, params))
733 {
734 return false;
735 }
736 break;
737
738 case GL_TEXTURE_SWIZZLE_R:
739 case GL_TEXTURE_SWIZZLE_G:
740 case GL_TEXTURE_SWIZZLE_B:
741 case GL_TEXTURE_SWIZZLE_A:
742 switch (ConvertToGLenum(params[0]))
743 {
744 case GL_RED:
745 case GL_GREEN:
746 case GL_BLUE:
747 case GL_ALPHA:
748 case GL_ZERO:
749 case GL_ONE:
750 break;
751
752 default:
753 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
754 return false;
755 }
756 break;
757
758 case GL_TEXTURE_BASE_LEVEL:
759 if (params[0] < 0)
760 {
761 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
762 return false;
763 }
764 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
765 {
766 context->handleError(
767 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
768 return false;
769 }
770 break;
771
772 case GL_TEXTURE_MAX_LEVEL:
773 if (params[0] < 0)
774 {
775 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
776 return false;
777 }
778 break;
779
780 default:
781 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
782 return false;
783 }
784
785 return true;
786}
787
788template <typename ParamType>
789bool ValidateSamplerParameterBase(Context *context,
790 GLuint sampler,
791 GLenum pname,
792 GLsizei bufSize,
793 ParamType *params)
794{
795 if (context->getClientMajorVersion() < 3)
796 {
797 context->handleError(
798 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
799 return false;
800 }
801
802 if (!context->isSampler(sampler))
803 {
804 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
805 return false;
806 }
807
808 const GLsizei minBufSize = 1;
809 if (bufSize >= 0 && bufSize < minBufSize)
810 {
811 context->handleError(
812 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
813 return false;
814 }
815
816 switch (pname)
817 {
818 case GL_TEXTURE_WRAP_S:
819 case GL_TEXTURE_WRAP_T:
820 case GL_TEXTURE_WRAP_R:
821 if (!ValidateTextureWrapModeValue(context, params, false))
822 {
823 return false;
824 }
825 break;
826
827 case GL_TEXTURE_MIN_FILTER:
828 if (!ValidateTextureMinFilterValue(context, params, false))
829 {
830 return false;
831 }
832 break;
833
834 case GL_TEXTURE_MAG_FILTER:
835 if (!ValidateTextureMagFilterValue(context, params))
836 {
837 return false;
838 }
839 break;
840
841 case GL_TEXTURE_MIN_LOD:
842 case GL_TEXTURE_MAX_LOD:
843 // any value is permissible
844 break;
845
846 case GL_TEXTURE_COMPARE_MODE:
847 if (!ValidateTextureCompareModeValue(context, params))
848 {
849 return false;
850 }
851 break;
852
853 case GL_TEXTURE_COMPARE_FUNC:
854 if (!ValidateTextureCompareFuncValue(context, params))
855 {
856 return false;
857 }
858 break;
859
860 default:
861 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
862 return false;
863 }
864
865 return true;
866}
867
868bool ValidateGetSamplerParameterBase(Context *context,
869 GLuint sampler,
870 GLenum pname,
871 GLsizei *length)
872{
873 if (length)
874 {
875 *length = 0;
876 }
877
878 if (context->getClientMajorVersion() < 3)
879 {
880 context->handleError(
881 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
882 return false;
883 }
884
885 if (!context->isSampler(sampler))
886 {
887 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
888 return false;
889 }
890
891 switch (pname)
892 {
893 case GL_TEXTURE_WRAP_S:
894 case GL_TEXTURE_WRAP_T:
895 case GL_TEXTURE_WRAP_R:
896 case GL_TEXTURE_MIN_FILTER:
897 case GL_TEXTURE_MAG_FILTER:
898 case GL_TEXTURE_MIN_LOD:
899 case GL_TEXTURE_MAX_LOD:
900 case GL_TEXTURE_COMPARE_MODE:
901 case GL_TEXTURE_COMPARE_FUNC:
902 break;
903
904 default:
905 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
906 return false;
907 }
908
909 if (length)
910 {
911 *length = 1;
912 }
913 return true;
914}
915
Geoff Lang0b031062016-10-13 14:30:04 -0400916bool ValidateGetVertexAttribBase(Context *context,
917 GLuint index,
918 GLenum pname,
919 GLsizei *length,
920 bool pointer,
921 bool pureIntegerEntryPoint)
922{
923 if (length)
924 {
925 *length = 0;
926 }
927
928 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
929 {
930 context->handleError(
931 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
932 return false;
933 }
934
935 if (index >= context->getCaps().maxVertexAttributes)
936 {
937 context->handleError(Error(
938 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
939 return false;
940 }
941
942 if (pointer)
943 {
944 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
945 {
946 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
947 return false;
948 }
949 }
950 else
951 {
952 switch (pname)
953 {
954 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
955 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
956 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
957 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
958 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
959 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
960 case GL_CURRENT_VERTEX_ATTRIB:
961 break;
962
963 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
964 static_assert(
965 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
966 "ANGLE extension enums not equal to GL enums.");
967 if (context->getClientMajorVersion() < 3 &&
968 !context->getExtensions().instancedArrays)
969 {
970 context->handleError(Error(GL_INVALID_ENUM,
971 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
972 "3.0 or GL_ANGLE_instanced_arrays."));
973 return false;
974 }
975 break;
976
977 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
978 if (context->getClientMajorVersion() < 3)
979 {
980 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
981 return false;
982 }
983 break;
984
985 default:
986 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
987 return false;
988 }
989 }
990
991 if (length)
992 {
993 if (pname == GL_CURRENT_VERTEX_ATTRIB)
994 {
995 *length = 4;
996 }
997 else
998 {
999 *length = 1;
1000 }
1001 }
1002
1003 return true;
1004}
1005
Geoff Langf41a7152016-09-19 15:11:17 -04001006} // anonymous namespace
1007
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001008bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001009{
Jamie Madilld7460c72014-01-21 16:38:14 -05001010 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001011 {
Jamie Madilld7460c72014-01-21 16:38:14 -05001012 case GL_TEXTURE_2D:
1013 case GL_TEXTURE_CUBE_MAP:
1014 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001015
Jamie Madilld7460c72014-01-21 16:38:14 -05001016 case GL_TEXTURE_3D:
1017 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001018 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001019
1020 default:
1021 return false;
1022 }
Jamie Madill35d15012013-10-07 10:46:37 -04001023}
1024
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001025bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1026{
1027 switch (target)
1028 {
1029 case GL_TEXTURE_2D:
1030 case GL_TEXTURE_CUBE_MAP:
1031 return true;
1032
1033 default:
1034 return false;
1035 }
1036}
1037
1038bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1039{
1040 switch (target)
1041 {
1042 case GL_TEXTURE_3D:
1043 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001044 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001045
1046 default:
1047 return false;
1048 }
1049}
1050
Ian Ewellbda75592016-04-18 17:25:54 -04001051// Most texture GL calls are not compatible with external textures, so we have a separate validation
1052// function for use in the GL calls that do
1053bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1054{
1055 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1056 (context->getExtensions().eglImageExternal ||
1057 context->getExtensions().eglStreamConsumerExternal);
1058}
1059
Shannon Woods4dfed832014-03-17 20:03:39 -04001060// This function differs from ValidTextureTarget in that the target must be
1061// usable as the destination of a 2D operation-- so a cube face is valid, but
1062// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001063// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001064bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001065{
1066 switch (target)
1067 {
1068 case GL_TEXTURE_2D:
1069 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1070 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1071 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1072 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1073 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1074 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1075 return true;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001076 default:
1077 return false;
1078 }
1079}
1080
1081bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1082{
1083 switch (target)
1084 {
Shannon Woods4dfed832014-03-17 20:03:39 -04001085 case GL_TEXTURE_3D:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001086 case GL_TEXTURE_2D_ARRAY:
1087 return true;
Shannon Woods4dfed832014-03-17 20:03:39 -04001088 default:
1089 return false;
1090 }
1091}
1092
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001093bool ValidFramebufferTarget(GLenum target)
1094{
Geoff Langd4475812015-03-18 10:53:05 -04001095 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
1096 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001097
1098 switch (target)
1099 {
1100 case GL_FRAMEBUFFER: return true;
1101 case GL_READ_FRAMEBUFFER: return true;
1102 case GL_DRAW_FRAMEBUFFER: return true;
1103 default: return false;
1104 }
1105}
1106
Jamie Madill29639852016-09-02 15:00:09 -04001107bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001108{
1109 switch (target)
1110 {
1111 case GL_ARRAY_BUFFER:
1112 case GL_ELEMENT_ARRAY_BUFFER:
1113 return true;
1114
Jamie Madill8c96d582014-03-05 15:01:23 -05001115 case GL_PIXEL_PACK_BUFFER:
1116 case GL_PIXEL_UNPACK_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001117 return (context->getExtensions().pixelBufferObject ||
1118 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001119
Shannon Woodsb3801742014-03-27 14:59:19 -04001120 case GL_COPY_READ_BUFFER:
1121 case GL_COPY_WRITE_BUFFER:
Jamie Madill8c96d582014-03-05 15:01:23 -05001122 case GL_TRANSFORM_FEEDBACK_BUFFER:
1123 case GL_UNIFORM_BUFFER:
Martin Radev1be913c2016-07-11 17:59:16 +03001124 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001125
1126 default:
1127 return false;
1128 }
1129}
1130
Geoff Langff5b2d52016-09-07 11:32:23 -04001131bool ValidBufferParameter(const ValidationContext *context, GLenum pname, GLsizei *numParams)
Jamie Madill70656a62014-03-05 15:01:26 -05001132{
Geoff Langff5b2d52016-09-07 11:32:23 -04001133 // All buffer parameter queries return one value.
1134 *numParams = 1;
1135
Geoff Langcc6f55d2015-03-20 13:01:02 -04001136 const Extensions &extensions = context->getExtensions();
1137
Jamie Madill70656a62014-03-05 15:01:26 -05001138 switch (pname)
1139 {
1140 case GL_BUFFER_USAGE:
1141 case GL_BUFFER_SIZE:
1142 return true;
1143
Geoff Langcc6f55d2015-03-20 13:01:02 -04001144 case GL_BUFFER_ACCESS_OES:
1145 return extensions.mapBuffer;
1146
1147 case GL_BUFFER_MAPPED:
1148 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
Martin Radev1be913c2016-07-11 17:59:16 +03001149 return (context->getClientMajorVersion() >= 3) || extensions.mapBuffer ||
1150 extensions.mapBufferRange;
Geoff Langcc6f55d2015-03-20 13:01:02 -04001151
Jamie Madill70656a62014-03-05 15:01:26 -05001152 // GL_BUFFER_MAP_POINTER is a special case, and may only be
1153 // queried with GetBufferPointerv
1154 case GL_BUFFER_ACCESS_FLAGS:
Jamie Madill70656a62014-03-05 15:01:26 -05001155 case GL_BUFFER_MAP_OFFSET:
1156 case GL_BUFFER_MAP_LENGTH:
Martin Radev1be913c2016-07-11 17:59:16 +03001157 return (context->getClientMajorVersion() >= 3) || extensions.mapBufferRange;
Jamie Madill70656a62014-03-05 15:01:26 -05001158
1159 default:
1160 return false;
1161 }
1162}
1163
Jamie Madillc29968b2016-01-20 11:17:23 -05001164bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001165{
Jamie Madillc29968b2016-01-20 11:17:23 -05001166 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001167 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001168 switch (target)
1169 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001170 case GL_TEXTURE_2D:
1171 maxDimension = caps.max2DTextureSize;
1172 break;
Geoff Langce635692013-09-24 13:56:32 -04001173 case GL_TEXTURE_CUBE_MAP:
1174 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1175 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1176 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1177 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1178 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
Jamie Madillc29968b2016-01-20 11:17:23 -05001179 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1180 maxDimension = caps.maxCubeMapTextureSize;
1181 break;
1182 case GL_TEXTURE_3D:
1183 maxDimension = caps.max3DTextureSize;
1184 break;
1185 case GL_TEXTURE_2D_ARRAY:
1186 maxDimension = caps.max2DTextureSize;
1187 break;
Geoff Langce635692013-09-24 13:56:32 -04001188 default: UNREACHABLE();
1189 }
1190
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001191 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001192}
1193
Austin Kinross08528e12015-10-07 16:24:40 -07001194bool ValidImageSizeParameters(const Context *context,
1195 GLenum target,
1196 GLint level,
1197 GLsizei width,
1198 GLsizei height,
1199 GLsizei depth,
1200 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001201{
1202 if (level < 0 || width < 0 || height < 0 || depth < 0)
1203 {
1204 return false;
1205 }
1206
Austin Kinross08528e12015-10-07 16:24:40 -07001207 // TexSubImage parameters can be NPOT without textureNPOT extension,
1208 // as long as the destination texture is POT.
1209 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001210 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001211 {
1212 return false;
1213 }
1214
1215 if (!ValidMipLevel(context, target, level))
1216 {
1217 return false;
1218 }
1219
1220 return true;
1221}
1222
Geoff Lang0d8b7242015-09-09 14:56:53 -04001223bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1224{
1225 // List of compressed format that require that the texture size is smaller than or a multiple of
1226 // the compressed block size.
1227 switch (internalFormat)
1228 {
1229 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1230 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1231 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1232 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001233 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001234 return true;
1235
1236 default:
1237 return false;
1238 }
1239}
1240
Jamie Madillc29968b2016-01-20 11:17:23 -05001241bool ValidCompressedImageSize(const ValidationContext *context,
1242 GLenum internalFormat,
1243 GLsizei width,
1244 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001245{
Geoff Lang5d601382014-07-22 15:14:06 -04001246 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1247 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001248 {
1249 return false;
1250 }
1251
Geoff Lang0d8b7242015-09-09 14:56:53 -04001252 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001253 {
1254 return false;
1255 }
1256
Geoff Lang0d8b7242015-09-09 14:56:53 -04001257 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1258 {
1259 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1260 width % formatInfo.compressedBlockWidth != 0) ||
1261 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1262 height % formatInfo.compressedBlockHeight != 0))
1263 {
1264 return false;
1265 }
1266 }
1267
Geoff Langd4f180b2013-09-24 13:57:44 -04001268 return true;
1269}
1270
Geoff Langff5b2d52016-09-07 11:32:23 -04001271bool ValidImageDataSize(ValidationContext *context,
1272 GLenum textureTarget,
1273 GLsizei width,
1274 GLsizei height,
1275 GLsizei depth,
1276 GLenum internalFormat,
1277 GLenum type,
1278 const GLvoid *pixels,
1279 GLsizei imageSize)
1280{
1281 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1282 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1283 {
1284 // Checks are not required
1285 return true;
1286 }
1287
1288 // ...the data would be unpacked from the buffer object such that the memory reads required
1289 // would exceed the data store size.
1290 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1291 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1292 const gl::Extents size(width, height, depth);
1293 const auto &unpack = context->getGLState().getUnpackState();
1294
1295 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1296 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1297 if (endByteOrErr.isError())
1298 {
1299 context->handleError(endByteOrErr.getError());
1300 return false;
1301 }
1302
1303 GLuint endByte = endByteOrErr.getResult();
1304
1305 if (pixelUnpackBuffer)
1306 {
1307 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1308 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1309 checkedEndByte += checkedOffset;
1310
1311 if (!checkedEndByte.IsValid() ||
1312 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1313 {
1314 // Overflow past the end of the buffer
1315 context->handleError(Error(GL_INVALID_OPERATION));
1316 return false;
1317 }
1318 }
1319 else
1320 {
1321 ASSERT(imageSize >= 0);
1322 if (pixels == nullptr && imageSize != 0)
1323 {
1324 context->handleError(
1325 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
1326 }
1327
1328 if (endByte > static_cast<GLuint>(imageSize))
1329 {
1330 context->handleError(
1331 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1332 return false;
1333 }
1334 }
1335
1336 return true;
1337}
1338
Geoff Lang37dde692014-01-31 16:34:54 -05001339bool ValidQueryType(const Context *context, GLenum queryType)
1340{
Geoff Langd4475812015-03-18 10:53:05 -04001341 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
1342 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001343
1344 switch (queryType)
1345 {
1346 case GL_ANY_SAMPLES_PASSED:
1347 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1348 return true;
1349 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
Martin Radev1be913c2016-07-11 17:59:16 +03001350 return (context->getClientMajorVersion() >= 3);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001351 case GL_TIME_ELAPSED_EXT:
1352 return context->getExtensions().disjointTimerQuery;
Geoff Lang2b4ce802016-04-28 13:34:50 -04001353 case GL_COMMANDS_COMPLETED_CHROMIUM:
1354 return context->getExtensions().syncQuery;
Geoff Lang37dde692014-01-31 16:34:54 -05001355 default:
1356 return false;
1357 }
1358}
1359
Jamie Madillef300b12016-10-07 15:12:09 -04001360Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001361{
1362 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the
1363 // error INVALID_VALUE if the provided name is not the name of either a shader or program object and
1364 // INVALID_OPERATION if the provided name identifies an object that is not the expected type."
1365
Dian Xiang769769a2015-09-09 15:20:08 -07001366 Program *validProgram = context->getProgram(id);
1367
1368 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001369 {
Dian Xiang769769a2015-09-09 15:20:08 -07001370 if (context->getShader(id))
1371 {
Jamie Madill437fa652016-05-03 15:13:24 -04001372 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001373 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1374 }
1375 else
1376 {
Jamie Madill437fa652016-05-03 15:13:24 -04001377 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001378 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001379 }
Dian Xiang769769a2015-09-09 15:20:08 -07001380
1381 return validProgram;
1382}
1383
Jamie Madillef300b12016-10-07 15:12:09 -04001384Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001385{
1386 // See ValidProgram for spec details.
1387
1388 Shader *validShader = context->getShader(id);
1389
1390 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001391 {
Dian Xiang769769a2015-09-09 15:20:08 -07001392 if (context->getProgram(id))
1393 {
Jamie Madill437fa652016-05-03 15:13:24 -04001394 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001395 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1396 }
1397 else
1398 {
Jamie Madill437fa652016-05-03 15:13:24 -04001399 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001400 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001401 }
Dian Xiang769769a2015-09-09 15:20:08 -07001402
1403 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001404}
1405
Geoff Langb1196682014-07-23 13:47:29 -04001406bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001407{
1408 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1409 {
1410 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1411
Geoff Langaae65a42014-05-26 12:43:44 -04001412 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001413 {
Jamie Madill437fa652016-05-03 15:13:24 -04001414 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001415 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001416 }
1417 }
1418 else
1419 {
1420 switch (attachment)
1421 {
1422 case GL_DEPTH_ATTACHMENT:
1423 case GL_STENCIL_ATTACHMENT:
Martin Radev1be913c2016-07-11 17:59:16 +03001424 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001425
1426 case GL_DEPTH_STENCIL_ATTACHMENT:
Geoff Langc287ea62016-09-16 14:46:51 -04001427 if (!context->getExtensions().webglCompatibility &&
1428 context->getClientMajorVersion() < 3)
Martin Radev1be913c2016-07-11 17:59:16 +03001429 {
1430 context->handleError(Error(GL_INVALID_ENUM));
1431 return false;
1432 }
1433 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001434
1435 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001436 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03001437 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001438 }
1439 }
1440
1441 return true;
1442}
1443
Corentin Walleze0902642014-11-04 12:32:15 -08001444bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
1445 GLenum internalformat, GLsizei width, GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001446{
1447 switch (target)
1448 {
1449 case GL_RENDERBUFFER:
1450 break;
1451 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001452 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001453 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001454 }
1455
1456 if (width < 0 || height < 0 || samples < 0)
1457 {
Jamie Madill437fa652016-05-03 15:13:24 -04001458 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001459 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001460 }
1461
Geoff Langd87878e2014-09-19 15:42:59 -04001462 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1463 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001464 {
Jamie Madill437fa652016-05-03 15:13:24 -04001465 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001466 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001467 }
1468
1469 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1470 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
Corentin Walleze0902642014-11-04 12:32:15 -08001471 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001472 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001473 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001474 {
Jamie Madill437fa652016-05-03 15:13:24 -04001475 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001476 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001477 }
1478
Geoff Langaae65a42014-05-26 12:43:44 -04001479 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001480 {
Jamie Madill437fa652016-05-03 15:13:24 -04001481 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001482 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001483 }
1484
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001485 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001486 if (handle == 0)
1487 {
Jamie Madill437fa652016-05-03 15:13:24 -04001488 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001489 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001490 }
1491
1492 return true;
1493}
1494
Corentin Walleze0902642014-11-04 12:32:15 -08001495bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
1496 GLenum internalformat, GLsizei width, GLsizei height)
1497{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001498 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001499
1500 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001501 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001502 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001503 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001504 {
Jamie Madill437fa652016-05-03 15:13:24 -04001505 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001506 return false;
1507 }
1508
1509 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1510 // the specified storage. This is different than ES 3.0 in which a sample number higher
1511 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001512 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001513 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001514 {
Geoff Langa4903b72015-03-02 16:02:48 -08001515 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1516 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1517 {
Jamie Madill437fa652016-05-03 15:13:24 -04001518 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001519 return false;
1520 }
Corentin Walleze0902642014-11-04 12:32:15 -08001521 }
1522
1523 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
1524}
1525
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001526bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
1527 GLenum renderbuffertarget, GLuint renderbuffer)
1528{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001529 if (!ValidFramebufferTarget(target))
1530 {
Jamie Madill437fa652016-05-03 15:13:24 -04001531 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001532 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001533 }
1534
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001535 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001536
Jamie Madill84115c92015-04-23 15:00:07 -04001537 ASSERT(framebuffer);
1538 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001539 {
Jamie Madill437fa652016-05-03 15:13:24 -04001540 context->handleError(
1541 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001542 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001543 }
1544
Jamie Madillb4472272014-07-03 10:38:55 -04001545 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001546 {
Jamie Madillb4472272014-07-03 10:38:55 -04001547 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001548 }
1549
Jamie Madillab9d82c2014-01-21 16:38:14 -05001550 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1551 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1552 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1553 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1554 if (renderbuffer != 0)
1555 {
1556 if (!context->getRenderbuffer(renderbuffer))
1557 {
Jamie Madill437fa652016-05-03 15:13:24 -04001558 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001559 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001560 }
1561 }
1562
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001563 return true;
1564}
1565
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001566bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001567 GLint srcX0,
1568 GLint srcY0,
1569 GLint srcX1,
1570 GLint srcY1,
1571 GLint dstX0,
1572 GLint dstY0,
1573 GLint dstX1,
1574 GLint dstY1,
1575 GLbitfield mask,
1576 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001577{
1578 switch (filter)
1579 {
1580 case GL_NEAREST:
1581 break;
1582 case GL_LINEAR:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001583 break;
1584 default:
Jamie Madill437fa652016-05-03 15:13:24 -04001585 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001586 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001587 }
1588
1589 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1590 {
Jamie Madill437fa652016-05-03 15:13:24 -04001591 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001592 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001593 }
1594
1595 if (mask == 0)
1596 {
1597 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1598 // buffers are copied.
1599 return false;
1600 }
1601
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001602 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1603 // color buffer, leaving only nearest being unfiltered from above
1604 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1605 {
Jamie Madill437fa652016-05-03 15:13:24 -04001606 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001607 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001608 }
1609
Jamie Madill51f40ec2016-06-15 14:06:00 -04001610 const auto &glState = context->getGLState();
1611 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1612 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001613
1614 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001615 {
Jamie Madill437fa652016-05-03 15:13:24 -04001616 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001617 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001618 }
1619
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001620 if (readFramebuffer->id() == drawFramebuffer->id())
1621 {
1622 context->handleError(Error(GL_INVALID_OPERATION));
1623 return false;
1624 }
1625
Jamie Madill51f40ec2016-06-15 14:06:00 -04001626 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001627 {
Jamie Madill437fa652016-05-03 15:13:24 -04001628 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001629 return false;
1630 }
1631
Jamie Madill51f40ec2016-06-15 14:06:00 -04001632 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001633 {
Jamie Madill437fa652016-05-03 15:13:24 -04001634 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001635 return false;
1636 }
1637
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001638 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001639 {
Jamie Madill437fa652016-05-03 15:13:24 -04001640 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001641 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001642 }
1643
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001644 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1645
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001646 if (mask & GL_COLOR_BUFFER_BIT)
1647 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001648 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1649 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001650 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001651
1652 if (readColorBuffer && drawColorBuffer)
1653 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001654 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001655
Geoff Langa15472a2015-08-11 11:48:03 -04001656 for (size_t drawbufferIdx = 0;
1657 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001658 {
Geoff Langa15472a2015-08-11 11:48:03 -04001659 const FramebufferAttachment *attachment =
1660 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1661 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001662 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001663 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001664
Geoff Langb2f3d052013-08-13 12:49:27 -04001665 // The GL ES 3.0.2 spec (pg 193) states that:
1666 // 1) If the read buffer is fixed point format, the draw buffer must be as well
1667 // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well
1668 // 3) If the read buffer is a signed integer format, the draw buffer must be as well
Jamie Madill6163c752015-12-07 16:32:59 -05001669 // Changes with EXT_color_buffer_float:
1670 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001671 GLenum readComponentType = readFormat.info->componentType;
1672 GLenum drawComponentType = drawFormat.info->componentType;
Jamie Madill6163c752015-12-07 16:32:59 -05001673 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
1674 readComponentType == GL_SIGNED_NORMALIZED);
1675 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1676 drawComponentType == GL_SIGNED_NORMALIZED);
1677
1678 if (extensions.colorBufferFloat)
1679 {
1680 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1681 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1682
1683 if (readFixedOrFloat != drawFixedOrFloat)
1684 {
Jamie Madill437fa652016-05-03 15:13:24 -04001685 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001686 "If the read buffer contains fixed-point or "
1687 "floating-point values, the draw buffer "
1688 "must as well."));
1689 return false;
1690 }
1691 }
1692 else if (readFixedPoint != drawFixedPoint)
1693 {
Jamie Madill437fa652016-05-03 15:13:24 -04001694 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001695 "If the read buffer contains fixed-point "
1696 "values, the draw buffer must as well."));
1697 return false;
1698 }
1699
1700 if (readComponentType == GL_UNSIGNED_INT &&
1701 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001702 {
Jamie Madill437fa652016-05-03 15:13:24 -04001703 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001704 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001705 }
1706
Jamie Madill6163c752015-12-07 16:32:59 -05001707 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001708 {
Jamie Madill437fa652016-05-03 15:13:24 -04001709 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001710 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001711 }
1712
Jamie Madilla3944d42016-07-22 22:13:26 -04001713 if (readColorBuffer->getSamples() > 0 &&
1714 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001715 {
Jamie Madill437fa652016-05-03 15:13:24 -04001716 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001717 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001718 }
1719 }
1720 }
1721
Jamie Madilla3944d42016-07-22 22:13:26 -04001722 if ((readFormat.info->componentType == GL_INT ||
1723 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1724 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001725 {
Jamie Madill437fa652016-05-03 15:13:24 -04001726 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001727 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001728 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001729 }
1730 }
1731
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001732 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
1733 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1734 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001735 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001736 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001737 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001738 const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
1739 const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001740
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001741 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001742 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001743 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001744 {
Jamie Madill437fa652016-05-03 15:13:24 -04001745 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001746 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001747 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001748
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001749 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001750 {
Jamie Madill437fa652016-05-03 15:13:24 -04001751 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001752 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001753 }
1754 }
1755 }
1756 }
1757
1758 return true;
1759}
1760
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001761bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001762 GLint x,
1763 GLint y,
1764 GLsizei width,
1765 GLsizei height,
1766 GLenum format,
1767 GLenum type,
1768 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05001769{
Geoff Lang62fce5b2016-09-30 10:46:35 -04001770 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
1771}
1772
1773bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
1774 GLint x,
1775 GLint y,
1776 GLsizei width,
1777 GLsizei height,
1778 GLenum format,
1779 GLenum type,
1780 GLsizei bufSize,
1781 GLsizei *length,
1782 GLvoid *pixels)
1783{
1784 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001785 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001786 return false;
1787 }
1788
Geoff Lang62fce5b2016-09-30 10:46:35 -04001789 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1790 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001791 {
Geoff Langb1196682014-07-23 13:47:29 -04001792 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001793 }
1794
Geoff Lang62fce5b2016-09-30 10:46:35 -04001795 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001796 {
Geoff Langb1196682014-07-23 13:47:29 -04001797 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001798 }
1799
Jamie Madillc29968b2016-01-20 11:17:23 -05001800 return true;
1801}
1802
1803bool ValidateReadnPixelsEXT(Context *context,
1804 GLint x,
1805 GLint y,
1806 GLsizei width,
1807 GLsizei height,
1808 GLenum format,
1809 GLenum type,
1810 GLsizei bufSize,
1811 GLvoid *pixels)
1812{
1813 if (bufSize < 0)
1814 {
Jamie Madill437fa652016-05-03 15:13:24 -04001815 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05001816 return false;
1817 }
1818
Geoff Lang62fce5b2016-09-30 10:46:35 -04001819 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
1820 pixels);
1821}
Jamie Madill26e91952014-03-05 15:01:27 -05001822
Geoff Lang62fce5b2016-09-30 10:46:35 -04001823bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
1824 GLint x,
1825 GLint y,
1826 GLsizei width,
1827 GLsizei height,
1828 GLenum format,
1829 GLenum type,
1830 GLsizei bufSize,
1831 GLsizei *length,
1832 GLvoid *data)
1833{
1834 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001835 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001836 return false;
1837 }
1838
Geoff Lang62fce5b2016-09-30 10:46:35 -04001839 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001840 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001841 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001842 }
1843
Geoff Lang62fce5b2016-09-30 10:46:35 -04001844 if (!ValidateRobustBufferSize(context, bufSize, *length))
1845 {
1846 return false;
1847 }
1848
1849 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001850}
1851
Olli Etuaho41997e72016-03-10 13:38:39 +02001852bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001853{
1854 if (!context->getExtensions().occlusionQueryBoolean &&
1855 !context->getExtensions().disjointTimerQuery)
1856 {
Jamie Madill437fa652016-05-03 15:13:24 -04001857 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001858 return false;
1859 }
1860
Olli Etuaho41997e72016-03-10 13:38:39 +02001861 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001862}
1863
Olli Etuaho41997e72016-03-10 13:38:39 +02001864bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001865{
1866 if (!context->getExtensions().occlusionQueryBoolean &&
1867 !context->getExtensions().disjointTimerQuery)
1868 {
Jamie Madill437fa652016-05-03 15:13:24 -04001869 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001870 return false;
1871 }
1872
Olli Etuaho41997e72016-03-10 13:38:39 +02001873 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001874}
1875
1876bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001877{
1878 if (!ValidQueryType(context, target))
1879 {
Jamie Madill437fa652016-05-03 15:13:24 -04001880 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001881 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001882 }
1883
1884 if (id == 0)
1885 {
Jamie Madill437fa652016-05-03 15:13:24 -04001886 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04001887 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001888 }
1889
1890 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1891 // of zero, if the active query object name for <target> is non-zero (for the
1892 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1893 // the active query for either target is non-zero), if <id> is the name of an
1894 // existing query object whose type does not match <target>, or if <id> is the
1895 // active query object name for any query type, the error INVALID_OPERATION is
1896 // generated.
1897
1898 // Ensure no other queries are active
1899 // NOTE: If other queries than occlusion are supported, we will need to check
1900 // separately that:
1901 // a) The query ID passed is not the current active query for any target/type
1902 // b) There are no active queries for the requested target (and in the case
1903 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1904 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001905
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001906 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001907 {
Jamie Madill437fa652016-05-03 15:13:24 -04001908 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04001909 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001910 }
1911
1912 Query *queryObject = context->getQuery(id, true, target);
1913
1914 // check that name was obtained with glGenQueries
1915 if (!queryObject)
1916 {
Jamie Madill437fa652016-05-03 15:13:24 -04001917 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04001918 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001919 }
1920
1921 // check for type mismatch
1922 if (queryObject->getType() != target)
1923 {
Jamie Madill437fa652016-05-03 15:13:24 -04001924 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04001925 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001926 }
1927
1928 return true;
1929}
1930
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001931bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1932{
1933 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001934 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001935 {
Jamie Madill437fa652016-05-03 15:13:24 -04001936 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001937 return false;
1938 }
1939
1940 return ValidateBeginQueryBase(context, target, id);
1941}
1942
1943bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001944{
1945 if (!ValidQueryType(context, target))
1946 {
Jamie Madill437fa652016-05-03 15:13:24 -04001947 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04001948 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001949 }
1950
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001951 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001952
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001953 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001954 {
Jamie Madill437fa652016-05-03 15:13:24 -04001955 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04001956 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001957 }
1958
Jamie Madill45c785d2014-05-13 14:09:34 -04001959 return true;
1960}
1961
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001962bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1963{
1964 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001965 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001966 {
Jamie Madill437fa652016-05-03 15:13:24 -04001967 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001968 return false;
1969 }
1970
1971 return ValidateEndQueryBase(context, target);
1972}
1973
1974bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1975{
1976 if (!context->getExtensions().disjointTimerQuery)
1977 {
Jamie Madill437fa652016-05-03 15:13:24 -04001978 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001979 return false;
1980 }
1981
1982 if (target != GL_TIMESTAMP_EXT)
1983 {
Jamie Madill437fa652016-05-03 15:13:24 -04001984 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001985 return false;
1986 }
1987
1988 Query *queryObject = context->getQuery(id, true, target);
1989 if (queryObject == nullptr)
1990 {
Jamie Madill437fa652016-05-03 15:13:24 -04001991 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001992 return false;
1993 }
1994
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001995 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001996 {
Jamie Madill437fa652016-05-03 15:13:24 -04001997 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001998 return false;
1999 }
2000
2001 return true;
2002}
2003
Geoff Lang2186c382016-10-14 10:54:54 -04002004bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002005{
Geoff Lang2186c382016-10-14 10:54:54 -04002006 if (numParams)
2007 {
2008 *numParams = 0;
2009 }
2010
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002011 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2012 {
Jamie Madill437fa652016-05-03 15:13:24 -04002013 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002014 return false;
2015 }
2016
2017 switch (pname)
2018 {
2019 case GL_CURRENT_QUERY_EXT:
2020 if (target == GL_TIMESTAMP_EXT)
2021 {
Jamie Madill437fa652016-05-03 15:13:24 -04002022 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002023 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2024 return false;
2025 }
2026 break;
2027 case GL_QUERY_COUNTER_BITS_EXT:
2028 if (!context->getExtensions().disjointTimerQuery ||
2029 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2030 {
Jamie Madill437fa652016-05-03 15:13:24 -04002031 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002032 return false;
2033 }
2034 break;
2035 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002036 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002037 return false;
2038 }
2039
Geoff Lang2186c382016-10-14 10:54:54 -04002040 if (numParams)
2041 {
2042 // All queries return only one value
2043 *numParams = 1;
2044 }
2045
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002046 return true;
2047}
2048
2049bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2050{
2051 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002052 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002053 {
Jamie Madill437fa652016-05-03 15:13:24 -04002054 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002055 return false;
2056 }
2057
Geoff Lang2186c382016-10-14 10:54:54 -04002058 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002059}
2060
Geoff Lang2186c382016-10-14 10:54:54 -04002061bool ValidateGetQueryivRobustANGLE(Context *context,
2062 GLenum target,
2063 GLenum pname,
2064 GLsizei bufSize,
2065 GLsizei *length,
2066 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002067{
Geoff Lang2186c382016-10-14 10:54:54 -04002068 if (!ValidateRobustEntryPoint(context, bufSize))
2069 {
2070 return false;
2071 }
2072
2073 if (!ValidateGetQueryivBase(context, target, pname, length))
2074 {
2075 return false;
2076 }
2077
2078 if (!ValidateRobustBufferSize(context, bufSize, *length))
2079 {
2080 return false;
2081 }
2082
2083 return true;
2084}
2085
2086bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2087{
2088 if (numParams)
2089 {
2090 *numParams = 0;
2091 }
2092
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002093 Query *queryObject = context->getQuery(id, false, GL_NONE);
2094
2095 if (!queryObject)
2096 {
Jamie Madill437fa652016-05-03 15:13:24 -04002097 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002098 return false;
2099 }
2100
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002101 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002102 {
Jamie Madill437fa652016-05-03 15:13:24 -04002103 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002104 return false;
2105 }
2106
2107 switch (pname)
2108 {
2109 case GL_QUERY_RESULT_EXT:
2110 case GL_QUERY_RESULT_AVAILABLE_EXT:
2111 break;
2112
2113 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002114 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002115 return false;
2116 }
2117
Geoff Lang2186c382016-10-14 10:54:54 -04002118 if (numParams)
2119 {
2120 *numParams = 1;
2121 }
2122
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002123 return true;
2124}
2125
2126bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2127{
2128 if (!context->getExtensions().disjointTimerQuery)
2129 {
Jamie Madill437fa652016-05-03 15:13:24 -04002130 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002131 return false;
2132 }
Geoff Lang2186c382016-10-14 10:54:54 -04002133 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2134}
2135
2136bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2137 GLuint id,
2138 GLenum pname,
2139 GLsizei bufSize,
2140 GLsizei *length,
2141 GLint *params)
2142{
2143 if (!context->getExtensions().disjointTimerQuery)
2144 {
2145 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2146 return false;
2147 }
2148
2149 if (!ValidateRobustEntryPoint(context, bufSize))
2150 {
2151 return false;
2152 }
2153
2154 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2155 {
2156 return false;
2157 }
2158
2159 if (!ValidateRobustBufferSize(context, bufSize, *length))
2160 {
2161 return false;
2162 }
2163
2164 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002165}
2166
2167bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2168{
2169 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002170 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002171 {
Jamie Madill437fa652016-05-03 15:13:24 -04002172 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002173 return false;
2174 }
Geoff Lang2186c382016-10-14 10:54:54 -04002175 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2176}
2177
2178bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2179 GLuint id,
2180 GLenum pname,
2181 GLsizei bufSize,
2182 GLsizei *length,
2183 GLuint *params)
2184{
2185 if (!context->getExtensions().disjointTimerQuery &&
2186 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2187 {
2188 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2189 return false;
2190 }
2191
2192 if (!ValidateRobustEntryPoint(context, bufSize))
2193 {
2194 return false;
2195 }
2196
2197 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2198 {
2199 return false;
2200 }
2201
2202 if (!ValidateRobustBufferSize(context, bufSize, *length))
2203 {
2204 return false;
2205 }
2206
2207 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002208}
2209
2210bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2211{
2212 if (!context->getExtensions().disjointTimerQuery)
2213 {
Jamie Madill437fa652016-05-03 15:13:24 -04002214 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002215 return false;
2216 }
Geoff Lang2186c382016-10-14 10:54:54 -04002217 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2218}
2219
2220bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2221 GLuint id,
2222 GLenum pname,
2223 GLsizei bufSize,
2224 GLsizei *length,
2225 GLint64 *params)
2226{
2227 if (!context->getExtensions().disjointTimerQuery)
2228 {
2229 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2230 return false;
2231 }
2232
2233 if (!ValidateRobustEntryPoint(context, bufSize))
2234 {
2235 return false;
2236 }
2237
2238 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2239 {
2240 return false;
2241 }
2242
2243 if (!ValidateRobustBufferSize(context, bufSize, *length))
2244 {
2245 return false;
2246 }
2247
2248 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002249}
2250
2251bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2252{
2253 if (!context->getExtensions().disjointTimerQuery)
2254 {
Jamie Madill437fa652016-05-03 15:13:24 -04002255 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002256 return false;
2257 }
Geoff Lang2186c382016-10-14 10:54:54 -04002258 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2259}
2260
2261bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2262 GLuint id,
2263 GLenum pname,
2264 GLsizei bufSize,
2265 GLsizei *length,
2266 GLuint64 *params)
2267{
2268 if (!context->getExtensions().disjointTimerQuery)
2269 {
2270 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2271 return false;
2272 }
2273
2274 if (!ValidateRobustEntryPoint(context, bufSize))
2275 {
2276 return false;
2277 }
2278
2279 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2280 {
2281 return false;
2282 }
2283
2284 if (!ValidateRobustBufferSize(context, bufSize, *length))
2285 {
2286 return false;
2287 }
2288
2289 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002290}
2291
Jamie Madill62d31cb2015-09-11 13:25:51 -04002292static bool ValidateUniformCommonBase(gl::Context *context,
2293 GLenum targetUniformType,
2294 GLint location,
2295 GLsizei count,
2296 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002297{
2298 if (count < 0)
2299 {
Jamie Madill437fa652016-05-03 15:13:24 -04002300 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002301 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002302 }
2303
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002304 gl::Program *program = context->getGLState().getProgram();
Geoff Lang7dd2e102014-11-10 15:19:26 -05002305 if (!program)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002306 {
Jamie Madill437fa652016-05-03 15:13:24 -04002307 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002308 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002309 }
2310
Geoff Langd8605522016-04-13 10:19:12 -04002311 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002312 {
2313 // Silently ignore the uniform command
2314 return false;
2315 }
2316
Geoff Lang7dd2e102014-11-10 15:19:26 -05002317 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002318 {
Jamie Madill437fa652016-05-03 15:13:24 -04002319 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002320 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002321 }
2322
Jamie Madill62d31cb2015-09-11 13:25:51 -04002323 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002324
2325 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002326 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002327 {
Jamie Madill437fa652016-05-03 15:13:24 -04002328 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002329 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002330 }
2331
Jamie Madill62d31cb2015-09-11 13:25:51 -04002332 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002333 return true;
2334}
2335
Jamie Madillaa981bd2014-05-20 10:55:55 -04002336bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2337{
2338 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002339 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2340 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002341 {
Jamie Madill437fa652016-05-03 15:13:24 -04002342 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002343 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002344 }
2345
Jamie Madill62d31cb2015-09-11 13:25:51 -04002346 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002347 if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform))
2348 {
2349 return false;
2350 }
2351
Jamie Madillf2575982014-06-25 16:04:54 -04002352 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002353 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002354 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2355 {
Jamie Madill437fa652016-05-03 15:13:24 -04002356 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002357 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002358 }
2359
2360 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002361}
2362
2363bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count,
2364 GLboolean transpose)
2365{
2366 // Check for ES3 uniform entry points
2367 int rows = VariableRowCount(matrixType);
2368 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002369 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002370 {
Jamie Madill437fa652016-05-03 15:13:24 -04002371 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002372 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002373 }
2374
Martin Radev1be913c2016-07-11 17:59:16 +03002375 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002376 {
Jamie Madill437fa652016-05-03 15:13:24 -04002377 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002378 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002379 }
2380
Jamie Madill62d31cb2015-09-11 13:25:51 -04002381 const LinkedUniform *uniform = nullptr;
Jamie Madill36398922014-05-20 14:51:53 -04002382 if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform))
2383 {
2384 return false;
2385 }
2386
2387 if (uniform->type != matrixType)
2388 {
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 Madill36398922014-05-20 14:51:53 -04002391 }
2392
2393 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002394}
2395
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002396bool ValidateStateQuery(ValidationContext *context,
2397 GLenum pname,
2398 GLenum *nativeType,
2399 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002400{
2401 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2402 {
Jamie Madill437fa652016-05-03 15:13:24 -04002403 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002404 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002405 }
2406
Jamie Madill0af26e12015-03-05 19:54:33 -05002407 const Caps &caps = context->getCaps();
2408
Jamie Madill893ab082014-05-16 16:56:10 -04002409 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2410 {
2411 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2412
Jamie Madill0af26e12015-03-05 19:54:33 -05002413 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002414 {
Jamie Madill437fa652016-05-03 15:13:24 -04002415 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002416 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002417 }
2418 }
2419
2420 switch (pname)
2421 {
2422 case GL_TEXTURE_BINDING_2D:
2423 case GL_TEXTURE_BINDING_CUBE_MAP:
2424 case GL_TEXTURE_BINDING_3D:
2425 case GL_TEXTURE_BINDING_2D_ARRAY:
Jamie Madill893ab082014-05-16 16:56:10 -04002426 break;
Ian Ewell54f87462016-03-10 13:47:21 -05002427 case GL_TEXTURE_BINDING_EXTERNAL_OES:
John Bauman18319182016-09-28 14:22:27 -07002428 if (!context->getExtensions().eglStreamConsumerExternal &&
2429 !context->getExtensions().eglImageExternal)
Ian Ewell54f87462016-03-10 13:47:21 -05002430 {
John Bauman18319182016-09-28 14:22:27 -07002431 context->handleError(Error(GL_INVALID_ENUM,
2432 "Neither NV_EGL_stream_consumer_external nor "
2433 "GL_OES_EGL_image_external extensions enabled"));
Ian Ewell54f87462016-03-10 13:47:21 -05002434 return false;
2435 }
2436 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002437
2438 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2439 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
2440 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002441 if (context->getGLState().getReadFramebuffer()->checkStatus(
2442 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002443 {
Jamie Madill437fa652016-05-03 15:13:24 -04002444 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002445 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002446 }
2447
Jamie Madill51f40ec2016-06-15 14:06:00 -04002448 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2449 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002450
2451 if (framebuffer->getReadBufferState() == GL_NONE)
2452 {
2453 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2454 return false;
2455 }
2456
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002457 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002458 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002459 {
Jamie Madill437fa652016-05-03 15:13:24 -04002460 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002461 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002462 }
2463 }
2464 break;
2465
2466 default:
2467 break;
2468 }
2469
2470 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002471 if (*numParams == 0)
2472 {
2473 return false;
2474 }
2475
2476 return true;
2477}
2478
2479bool ValidateRobustStateQuery(ValidationContext *context,
2480 GLenum pname,
2481 GLsizei bufSize,
2482 GLenum *nativeType,
2483 unsigned int *numParams)
2484{
2485 if (!ValidateRobustEntryPoint(context, bufSize))
2486 {
2487 return false;
2488 }
2489
2490 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2491 {
2492 return false;
2493 }
2494
2495 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002496 {
2497 return false;
2498 }
2499
2500 return true;
2501}
2502
Jamie Madillc29968b2016-01-20 11:17:23 -05002503bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2504 GLenum target,
2505 GLint level,
2506 GLenum internalformat,
2507 bool isSubImage,
2508 GLint xoffset,
2509 GLint yoffset,
2510 GLint zoffset,
2511 GLint x,
2512 GLint y,
2513 GLsizei width,
2514 GLsizei height,
2515 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002516 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002517{
Jamie Madill560a8d82014-05-21 13:06:20 -04002518 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2519 {
Jamie Madill437fa652016-05-03 15:13:24 -04002520 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002521 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002522 }
2523
2524 if (std::numeric_limits<GLsizei>::max() - xoffset < width || std::numeric_limits<GLsizei>::max() - yoffset < height)
2525 {
Jamie Madill437fa652016-05-03 15:13:24 -04002526 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002527 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002528 }
2529
2530 if (border != 0)
2531 {
Jamie Madill437fa652016-05-03 15:13:24 -04002532 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002533 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002534 }
2535
2536 if (!ValidMipLevel(context, target, level))
2537 {
Jamie Madill437fa652016-05-03 15:13:24 -04002538 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002539 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002540 }
2541
Jamie Madill51f40ec2016-06-15 14:06:00 -04002542 const auto &state = context->getGLState();
2543 auto readFramebuffer = state.getReadFramebuffer();
2544 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002545 {
Jamie Madill437fa652016-05-03 15:13:24 -04002546 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002547 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002548 }
2549
Jamie Madill51f40ec2016-06-15 14:06:00 -04002550 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002551 {
Jamie Madill437fa652016-05-03 15:13:24 -04002552 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002553 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002554 }
2555
Martin Radev138064f2016-07-15 12:03:41 +03002556 if (readFramebuffer->getReadBufferState() == GL_NONE)
2557 {
2558 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2559 return false;
2560 }
2561
Geoff Langaae65a42014-05-26 12:43:44 -04002562 const gl::Caps &caps = context->getCaps();
2563
Geoff Langaae65a42014-05-26 12:43:44 -04002564 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002565 switch (target)
2566 {
2567 case GL_TEXTURE_2D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002568 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002569 break;
2570
2571 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2572 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2573 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2574 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2575 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2576 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002577 maxDimension = caps.maxCubeMapTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002578 break;
2579
2580 case GL_TEXTURE_2D_ARRAY:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002581 maxDimension = caps.max2DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002582 break;
2583
2584 case GL_TEXTURE_3D:
Geoff Langa9be0dc2014-12-17 12:34:40 -05002585 maxDimension = caps.max3DTextureSize;
Jamie Madill560a8d82014-05-21 13:06:20 -04002586 break;
2587
2588 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002589 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002590 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002591 }
2592
Jamie Madillc29968b2016-01-20 11:17:23 -05002593 gl::Texture *texture =
2594 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002595 if (!texture)
2596 {
Jamie Madill437fa652016-05-03 15:13:24 -04002597 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002598 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002599 }
2600
Geoff Lang69cce582015-09-17 13:20:36 -04002601 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002602 {
Jamie Madill437fa652016-05-03 15:13:24 -04002603 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002604 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002605 }
2606
Geoff Lang5d601382014-07-22 15:14:06 -04002607 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2608
2609 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002610 {
Jamie Madill437fa652016-05-03 15:13:24 -04002611 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002612 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002613 }
2614
Geoff Langa9be0dc2014-12-17 12:34:40 -05002615 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04002616 {
Jamie Madill437fa652016-05-03 15:13:24 -04002617 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002618 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002619 }
2620
2621 if (isSubImage)
2622 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002623 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2624 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2625 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002626 {
Jamie Madill437fa652016-05-03 15:13:24 -04002627 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002628 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002629 }
2630 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002631 else
2632 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002633 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002634 {
Jamie Madill437fa652016-05-03 15:13:24 -04002635 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002636 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002637 }
2638
Martin Radev1be913c2016-07-11 17:59:16 +03002639 if (!formatInfo.textureSupport(context->getClientMajorVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002640 {
Jamie Madill437fa652016-05-03 15:13:24 -04002641 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002642 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002643 }
2644
2645 int maxLevelDimension = (maxDimension >> level);
2646 if (static_cast<int>(width) > maxLevelDimension || static_cast<int>(height) > maxLevelDimension)
2647 {
Jamie Madill437fa652016-05-03 15:13:24 -04002648 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002649 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002650 }
2651 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002652
Jamie Madill0c8abca2016-07-22 20:21:26 -04002653 if (textureFormatOut)
2654 {
2655 *textureFormatOut = texture->getFormat(target, level);
2656 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002657 return true;
2658}
2659
Jamie Madillf25855c2015-11-03 11:06:18 -05002660static bool ValidateDrawBase(ValidationContext *context,
2661 GLenum mode,
2662 GLsizei count,
2663 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002664{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002665 switch (mode)
2666 {
2667 case GL_POINTS:
2668 case GL_LINES:
2669 case GL_LINE_LOOP:
2670 case GL_LINE_STRIP:
2671 case GL_TRIANGLES:
2672 case GL_TRIANGLE_STRIP:
2673 case GL_TRIANGLE_FAN:
2674 break;
2675 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002676 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002677 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002678 }
2679
Jamie Madill250d33f2014-06-06 17:09:03 -04002680 if (count < 0)
2681 {
Jamie Madill437fa652016-05-03 15:13:24 -04002682 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002683 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002684 }
2685
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002686 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002687
Jamie Madill250d33f2014-06-06 17:09:03 -04002688 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002689 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002690 {
Jamie Madill437fa652016-05-03 15:13:24 -04002691 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002692 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002693 }
2694
Jamie Madill51f40ec2016-06-15 14:06:00 -04002695 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04002696 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04002697 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04002698 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
2699 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
2700 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
2701 const DepthStencilState &depthStencilState = state.getDepthStencilState();
2702 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2703 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04002704 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04002705 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2706 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04002707 {
2708 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2709 // Section 6.10 of the WebGL 1.0 spec
2710 ERR(
2711 "This ANGLE implementation does not support separate front/back stencil "
2712 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04002713 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04002714 return false;
2715 }
Jamie Madillac528012014-06-20 13:21:23 -04002716 }
2717
Jamie Madill51f40ec2016-06-15 14:06:00 -04002718 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002719 {
Jamie Madill437fa652016-05-03 15:13:24 -04002720 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002721 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002722 }
2723
Geoff Lang7dd2e102014-11-10 15:19:26 -05002724 gl::Program *program = state.getProgram();
2725 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002726 {
Jamie Madill437fa652016-05-03 15:13:24 -04002727 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002728 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002729 }
2730
Geoff Lang7dd2e102014-11-10 15:19:26 -05002731 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002732 {
Jamie Madill437fa652016-05-03 15:13:24 -04002733 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002734 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002735 }
2736
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002737 // Uniform buffer validation
2738 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
2739 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002740 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002741 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002742 const OffsetBindingPointer<Buffer> &uniformBuffer =
2743 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002744
Geoff Lang5d124a62015-09-15 13:03:27 -04002745 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002746 {
2747 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002748 context->handleError(
2749 Error(GL_INVALID_OPERATION,
2750 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002751 return false;
2752 }
2753
Geoff Lang5d124a62015-09-15 13:03:27 -04002754 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002755 if (uniformBufferSize == 0)
2756 {
2757 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002758 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002759 }
2760
Jamie Madill62d31cb2015-09-11 13:25:51 -04002761 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002762 {
2763 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002764 context->handleError(
2765 Error(GL_INVALID_OPERATION,
2766 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002767 return false;
2768 }
2769 }
2770
Jamie Madill250d33f2014-06-06 17:09:03 -04002771 // No-op if zero count
2772 return (count > 0);
2773}
2774
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002775bool ValidateDrawArrays(ValidationContext *context,
2776 GLenum mode,
2777 GLint first,
2778 GLsizei count,
2779 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002780{
Jamie Madillfd716582014-06-06 17:09:04 -04002781 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002782 {
Jamie Madill437fa652016-05-03 15:13:24 -04002783 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002784 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002785 }
2786
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002787 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002788 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002789 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() &&
2790 curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002791 {
2792 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2793 // that does not match the current transform feedback object's draw mode (if transform feedback
2794 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002795 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002796 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002797 }
2798
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002799 if (!ValidateDrawBase(context, mode, count, primcount))
2800 {
2801 return false;
2802 }
2803
2804 if (!ValidateDrawAttribs(context, primcount, count))
Jamie Madillfd716582014-06-06 17:09:04 -04002805 {
2806 return false;
2807 }
2808
2809 return true;
2810}
2811
Geoff Langb1196682014-07-23 13:47:29 -04002812bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002813{
2814 if (primcount < 0)
2815 {
Jamie Madill437fa652016-05-03 15:13:24 -04002816 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002817 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002818 }
2819
Jamie Madill2b976812014-08-25 15:47:49 -04002820 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04002821 {
2822 return false;
2823 }
2824
2825 // No-op if zero primitive count
2826 return (primcount > 0);
2827}
2828
Geoff Lang87a93302014-09-16 13:29:43 -04002829static bool ValidateDrawInstancedANGLE(Context *context)
2830{
2831 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002832 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04002833
Geoff Lang7dd2e102014-11-10 15:19:26 -05002834 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04002835
2836 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04002837 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04002838 {
2839 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04002840 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04002841 {
2842 return true;
2843 }
2844 }
2845
Jamie Madill437fa652016-05-03 15:13:24 -04002846 context->handleError(Error(GL_INVALID_OPERATION,
2847 "ANGLE_instanced_arrays requires that at least one active attribute"
2848 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04002849 return false;
2850}
2851
2852bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
2853{
2854 if (!ValidateDrawInstancedANGLE(context))
2855 {
2856 return false;
2857 }
2858
2859 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
2860}
2861
Jamie Madillf25855c2015-11-03 11:06:18 -05002862bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002863 GLenum mode,
2864 GLsizei count,
2865 GLenum type,
2866 const GLvoid *indices,
2867 GLsizei primcount,
2868 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002869{
Jamie Madill250d33f2014-06-06 17:09:03 -04002870 switch (type)
2871 {
2872 case GL_UNSIGNED_BYTE:
2873 case GL_UNSIGNED_SHORT:
Martin Radev1be913c2016-07-11 17:59:16 +03002874 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002875 case GL_UNSIGNED_INT:
Martin Radev1be913c2016-07-11 17:59:16 +03002876 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2877 {
2878 context->handleError(Error(GL_INVALID_ENUM));
2879 return false;
2880 }
2881 break;
Jamie Madill250d33f2014-06-06 17:09:03 -04002882 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002883 context->handleError(Error(GL_INVALID_ENUM));
Martin Radev1be913c2016-07-11 17:59:16 +03002884 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002885 }
2886
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002887 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002888
2889 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
Geoff Langbb0a0bb2015-03-27 12:16:57 -04002890 if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002891 {
2892 // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced
2893 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04002894 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002895 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002896 }
2897
2898 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002899 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002900 {
Jamie Madill437fa652016-05-03 15:13:24 -04002901 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002902 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002903 }
2904
Jamie Madill2b976812014-08-25 15:47:49 -04002905 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002906 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04002907 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002908 {
Jamie Madill437fa652016-05-03 15:13:24 -04002909 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002910 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002911 }
2912
Jamie Madillae3000b2014-08-25 15:47:51 -04002913 if (elementArrayBuffer)
2914 {
2915 const gl::Type &typeInfo = gl::GetTypeInfo(type);
2916
2917 GLint64 offset = reinterpret_cast<GLint64>(indices);
2918 GLint64 byteCount = static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count)+offset;
2919
2920 // check for integer overflows
2921 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
2922 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
2923 {
Jamie Madill437fa652016-05-03 15:13:24 -04002924 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04002925 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002926 }
2927
2928 // Check for reading past the end of the bound buffer object
2929 if (byteCount > elementArrayBuffer->getSize())
2930 {
Jamie Madill437fa652016-05-03 15:13:24 -04002931 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002932 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002933 }
2934 }
2935 else if (!indices)
2936 {
2937 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04002938 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002939 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002940 }
2941
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002942 if (!ValidateDrawBase(context, mode, count, primcount))
2943 {
2944 return false;
2945 }
2946
Jamie Madill2b976812014-08-25 15:47:49 -04002947 // Use max index to validate if our vertex buffers are large enough for the pull.
2948 // TODO: offer fast path, with disabled index validation.
2949 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
2950 if (elementArrayBuffer)
2951 {
Jacek Cabana5521de2014-10-01 17:23:46 +02002952 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04002953 Error error =
2954 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
2955 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04002956 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04002957 {
Jamie Madill437fa652016-05-03 15:13:24 -04002958 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04002959 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04002960 }
2961 }
2962 else
2963 {
Geoff Lang3edfe032015-09-04 16:38:24 -04002964 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04002965 }
2966
Jamie Madille79b1e12015-11-04 16:36:37 -05002967 // If we use an index greater than our maximum supported index range, return an error.
2968 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2969 // return an error if possible here.
2970 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
2971 {
Jamie Madill437fa652016-05-03 15:13:24 -04002972 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05002973 return false;
2974 }
2975
Jamie Madillbc4c4bc2016-03-23 21:04:43 -04002976 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04002977 {
2978 return false;
2979 }
2980
Geoff Lang3edfe032015-09-04 16:38:24 -04002981 // No op if there are no real indices in the index data (all are primitive restart).
2982 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04002983}
2984
Geoff Langb1196682014-07-23 13:47:29 -04002985bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04002986 GLenum mode,
2987 GLsizei count,
2988 GLenum type,
2989 const GLvoid *indices,
2990 GLsizei primcount,
2991 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04002992{
2993 if (primcount < 0)
2994 {
Jamie Madill437fa652016-05-03 15:13:24 -04002995 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002996 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002997 }
2998
Jamie Madill2b976812014-08-25 15:47:49 -04002999 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003000 {
3001 return false;
3002 }
3003
3004 // No-op zero primitive count
3005 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003006}
3007
Geoff Lang3edfe032015-09-04 16:38:24 -04003008bool ValidateDrawElementsInstancedANGLE(Context *context,
3009 GLenum mode,
3010 GLsizei count,
3011 GLenum type,
3012 const GLvoid *indices,
3013 GLsizei primcount,
3014 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003015{
3016 if (!ValidateDrawInstancedANGLE(context))
3017 {
3018 return false;
3019 }
3020
3021 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount, indexRangeOut);
3022}
3023
Geoff Langb1196682014-07-23 13:47:29 -04003024bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003025 GLuint texture, GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003026{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003027 if (!ValidFramebufferTarget(target))
3028 {
Jamie Madill437fa652016-05-03 15:13:24 -04003029 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003030 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003031 }
3032
3033 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003034 {
3035 return false;
3036 }
3037
Jamie Madill55ec3b12014-07-03 10:38:57 -04003038 if (texture != 0)
3039 {
3040 gl::Texture *tex = context->getTexture(texture);
3041
3042 if (tex == NULL)
3043 {
Jamie Madill437fa652016-05-03 15:13:24 -04003044 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003045 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003046 }
3047
3048 if (level < 0)
3049 {
Jamie Madill437fa652016-05-03 15:13:24 -04003050 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003051 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003052 }
3053 }
3054
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003055 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003056 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003057
Jamie Madill84115c92015-04-23 15:00:07 -04003058 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003059 {
Jamie Madill437fa652016-05-03 15:13:24 -04003060 context->handleError(
3061 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003062 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003063 }
3064
3065 return true;
3066}
3067
Geoff Langb1196682014-07-23 13:47:29 -04003068bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
Jamie Madill55ec3b12014-07-03 10:38:57 -04003069 GLenum textarget, GLuint texture, GLint level)
3070{
Geoff Lang95663912015-04-02 15:54:45 -04003071 // 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 +03003072 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3073 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003074 {
Jamie Madill437fa652016-05-03 15:13:24 -04003075 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003076 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003077 }
3078
3079 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003080 {
3081 return false;
3082 }
3083
Jamie Madill55ec3b12014-07-03 10:38:57 -04003084 if (texture != 0)
3085 {
3086 gl::Texture *tex = context->getTexture(texture);
3087 ASSERT(tex);
3088
Jamie Madill2a6564e2014-07-11 09:53:19 -04003089 const gl::Caps &caps = context->getCaps();
3090
Jamie Madill55ec3b12014-07-03 10:38:57 -04003091 switch (textarget)
3092 {
3093 case GL_TEXTURE_2D:
3094 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003095 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003096 {
Jamie Madill437fa652016-05-03 15:13:24 -04003097 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003098 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003099 }
3100 if (tex->getTarget() != GL_TEXTURE_2D)
3101 {
Jamie Madill437fa652016-05-03 15:13:24 -04003102 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003103 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003104 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003105 }
3106 break;
3107
3108 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3109 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3110 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3111 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3112 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3113 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3114 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003115 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003116 {
Jamie Madill437fa652016-05-03 15:13:24 -04003117 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003118 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003119 }
3120 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3121 {
Jamie Madill437fa652016-05-03 15:13:24 -04003122 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003123 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003124 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003125 }
3126 break;
3127
3128 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003129 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003130 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003131 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003132
Jamie Madilla3944d42016-07-22 22:13:26 -04003133 const Format &format = tex->getFormat(textarget, level);
3134 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003135 {
Jamie Madill437fa652016-05-03 15:13:24 -04003136 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003137 return false;
3138 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003139 }
3140
Jamie Madill570f7c82014-07-03 10:38:54 -04003141 return true;
3142}
3143
Geoff Langb1196682014-07-23 13:47:29 -04003144bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003145{
3146 if (program == 0)
3147 {
Jamie Madill437fa652016-05-03 15:13:24 -04003148 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003149 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003150 }
3151
Dian Xiang769769a2015-09-09 15:20:08 -07003152 gl::Program *programObject = GetValidProgram(context, program);
3153 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003154 {
3155 return false;
3156 }
3157
Jamie Madill0063c512014-08-25 15:47:53 -04003158 if (!programObject || !programObject->isLinked())
3159 {
Jamie Madill437fa652016-05-03 15:13:24 -04003160 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003161 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003162 }
3163
Geoff Lang7dd2e102014-11-10 15:19:26 -05003164 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003165 {
Jamie Madill437fa652016-05-03 15:13:24 -04003166 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003167 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003168 }
3169
Jamie Madill0063c512014-08-25 15:47:53 -04003170 return true;
3171}
3172
Geoff Langb1196682014-07-23 13:47:29 -04003173bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params)
Jamie Madill78f41802014-08-25 15:47:55 -04003174{
3175 return ValidateGetUniformBase(context, program, location);
3176}
3177
Geoff Langb1196682014-07-23 13:47:29 -04003178bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003179{
Jamie Madill78f41802014-08-25 15:47:55 -04003180 return ValidateGetUniformBase(context, program, location);
3181}
3182
Geoff Langf41d0ee2016-10-07 13:04:23 -04003183static bool ValidateSizedGetUniform(Context *context,
3184 GLuint program,
3185 GLint location,
3186 GLsizei bufSize,
3187 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003188{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003189 if (length)
3190 {
3191 *length = 0;
3192 }
3193
Jamie Madill78f41802014-08-25 15:47:55 -04003194 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003195 {
Jamie Madill78f41802014-08-25 15:47:55 -04003196 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003197 }
3198
Geoff Langf41d0ee2016-10-07 13:04:23 -04003199 if (bufSize < 0)
3200 {
3201 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3202 return false;
3203 }
3204
Jamie Madilla502c742014-08-28 17:19:13 -04003205 gl::Program *programObject = context->getProgram(program);
3206 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003207
Jamie Madill78f41802014-08-25 15:47:55 -04003208 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003209 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
3210 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003211 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003212 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003213 context->handleError(
3214 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003215 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003216 }
3217
Geoff Langf41d0ee2016-10-07 13:04:23 -04003218 if (length)
3219 {
3220 // Cast is safe because of comparison to bufSize.
3221 *length = static_cast<GLsizei>(requiredBytes);
3222 }
3223
Jamie Madill0063c512014-08-25 15:47:53 -04003224 return true;
3225}
3226
Geoff Langb1196682014-07-23 13:47:29 -04003227bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003228{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003229 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003230}
3231
Geoff Langb1196682014-07-23 13:47:29 -04003232bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params)
Jamie Madill0063c512014-08-25 15:47:53 -04003233{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003234 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3235}
3236
3237bool ValidateGetUniformfvRobustANGLE(Context *context,
3238 GLuint program,
3239 GLint location,
3240 GLsizei bufSize,
3241 GLsizei *length,
3242 GLfloat *params)
3243{
3244 if (!ValidateRobustEntryPoint(context, bufSize))
3245 {
3246 return false;
3247 }
3248
3249 // bufSize is validated in ValidateSizedGetUniform
3250 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3251}
3252
3253bool ValidateGetUniformivRobustANGLE(Context *context,
3254 GLuint program,
3255 GLint location,
3256 GLsizei bufSize,
3257 GLsizei *length,
3258 GLint *params)
3259{
3260 if (!ValidateRobustEntryPoint(context, bufSize))
3261 {
3262 return false;
3263 }
3264
3265 // bufSize is validated in ValidateSizedGetUniform
3266 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3267}
3268
3269bool ValidateGetUniformuivRobustANGLE(Context *context,
3270 GLuint program,
3271 GLint location,
3272 GLsizei bufSize,
3273 GLsizei *length,
3274 GLuint *params)
3275{
3276 if (!ValidateRobustEntryPoint(context, bufSize))
3277 {
3278 return false;
3279 }
3280
3281 if (context->getClientMajorVersion() < 3)
3282 {
3283 context->handleError(
3284 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3285 return false;
3286 }
3287
3288 // bufSize is validated in ValidateSizedGetUniform
3289 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003290}
3291
Austin Kinross08332632015-05-05 13:35:47 -07003292bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments,
3293 const GLenum *attachments, bool defaultFramebuffer)
3294{
3295 if (numAttachments < 0)
3296 {
Jamie Madill437fa652016-05-03 15:13:24 -04003297 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003298 return false;
3299 }
3300
3301 for (GLsizei i = 0; i < numAttachments; ++i)
3302 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003303 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003304 {
3305 if (defaultFramebuffer)
3306 {
Jamie Madill437fa652016-05-03 15:13:24 -04003307 context->handleError(Error(
3308 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003309 return false;
3310 }
3311
3312 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3313 {
Jamie Madill437fa652016-05-03 15:13:24 -04003314 context->handleError(Error(GL_INVALID_OPERATION,
3315 "Requested color attachment is greater than the maximum "
3316 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003317 return false;
3318 }
3319 }
3320 else
3321 {
3322 switch (attachments[i])
3323 {
3324 case GL_DEPTH_ATTACHMENT:
3325 case GL_STENCIL_ATTACHMENT:
3326 case GL_DEPTH_STENCIL_ATTACHMENT:
3327 if (defaultFramebuffer)
3328 {
Jamie Madill437fa652016-05-03 15:13:24 -04003329 context->handleError(
3330 Error(GL_INVALID_ENUM,
3331 "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003332 return false;
3333 }
3334 break;
3335 case GL_COLOR:
3336 case GL_DEPTH:
3337 case GL_STENCIL:
3338 if (!defaultFramebuffer)
3339 {
Jamie Madill437fa652016-05-03 15:13:24 -04003340 context->handleError(
3341 Error(GL_INVALID_ENUM,
3342 "Invalid attachment when the default framebuffer is not bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003343 return false;
3344 }
3345 break;
3346 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003347 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003348 return false;
3349 }
3350 }
3351 }
3352
3353 return true;
3354}
3355
Austin Kinross6ee1e782015-05-29 17:05:37 -07003356bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3357{
3358 // Note that debug marker calls must not set error state
3359
3360 if (length < 0)
3361 {
3362 return false;
3363 }
3364
3365 if (marker == nullptr)
3366 {
3367 return false;
3368 }
3369
3370 return true;
3371}
3372
3373bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3374{
3375 // Note that debug marker calls must not set error state
3376
3377 if (length < 0)
3378 {
3379 return false;
3380 }
3381
3382 if (length > 0 && marker == nullptr)
3383 {
3384 return false;
3385 }
3386
3387 return true;
3388}
3389
Geoff Langdcab33b2015-07-21 13:03:16 -04003390bool ValidateEGLImageTargetTexture2DOES(Context *context,
3391 egl::Display *display,
3392 GLenum target,
3393 egl::Image *image)
3394{
Geoff Langa8406172015-07-21 16:53:39 -04003395 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3396 {
Jamie Madill437fa652016-05-03 15:13:24 -04003397 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003398 return false;
3399 }
3400
3401 switch (target)
3402 {
3403 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003404 if (!context->getExtensions().eglImage)
3405 {
3406 context->handleError(Error(
3407 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3408 }
3409 break;
3410
3411 case GL_TEXTURE_EXTERNAL_OES:
3412 if (!context->getExtensions().eglImageExternal)
3413 {
3414 context->handleError(Error(
3415 GL_INVALID_ENUM,
3416 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3417 }
Geoff Langa8406172015-07-21 16:53:39 -04003418 break;
3419
3420 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003421 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003422 return false;
3423 }
3424
3425 if (!display->isValidImage(image))
3426 {
Jamie Madill437fa652016-05-03 15:13:24 -04003427 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003428 return false;
3429 }
3430
3431 if (image->getSamples() > 0)
3432 {
Jamie Madill437fa652016-05-03 15:13:24 -04003433 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003434 "cannot create a 2D texture from a multisampled EGL image."));
3435 return false;
3436 }
3437
Jamie Madilla3944d42016-07-22 22:13:26 -04003438 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003439 if (!textureCaps.texturable)
3440 {
Jamie Madill437fa652016-05-03 15:13:24 -04003441 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003442 "EGL image internal format is not supported as a texture."));
3443 return false;
3444 }
3445
Geoff Langdcab33b2015-07-21 13:03:16 -04003446 return true;
3447}
3448
3449bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3450 egl::Display *display,
3451 GLenum target,
3452 egl::Image *image)
3453{
Geoff Langa8406172015-07-21 16:53:39 -04003454 if (!context->getExtensions().eglImage)
3455 {
Jamie Madill437fa652016-05-03 15:13:24 -04003456 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003457 return false;
3458 }
3459
3460 switch (target)
3461 {
3462 case GL_RENDERBUFFER:
3463 break;
3464
3465 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003466 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003467 return false;
3468 }
3469
3470 if (!display->isValidImage(image))
3471 {
Jamie Madill437fa652016-05-03 15:13:24 -04003472 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003473 return false;
3474 }
3475
Jamie Madilla3944d42016-07-22 22:13:26 -04003476 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003477 if (!textureCaps.renderable)
3478 {
Jamie Madill437fa652016-05-03 15:13:24 -04003479 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003480 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3481 return false;
3482 }
3483
Geoff Langdcab33b2015-07-21 13:03:16 -04003484 return true;
3485}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003486
3487bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3488{
Geoff Lang36167ab2015-12-07 10:27:14 -05003489 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003490 {
3491 // The default VAO should always exist
3492 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003493 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003494 return false;
3495 }
3496
3497 return true;
3498}
3499
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003500bool ValidateLinkProgram(Context *context, GLuint program)
3501{
3502 if (context->hasActiveTransformFeedback(program))
3503 {
3504 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003505 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003506 "Cannot link program while program is associated with an active "
3507 "transform feedback object."));
3508 return false;
3509 }
3510 return true;
3511}
3512
Geoff Langc5629752015-12-07 16:29:04 -05003513bool ValidateProgramBinaryBase(Context *context,
3514 GLuint program,
3515 GLenum binaryFormat,
3516 const void *binary,
3517 GLint length)
3518{
3519 Program *programObject = GetValidProgram(context, program);
3520 if (programObject == nullptr)
3521 {
3522 return false;
3523 }
3524
3525 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3526 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3527 programBinaryFormats.end())
3528 {
Jamie Madill437fa652016-05-03 15:13:24 -04003529 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003530 return false;
3531 }
3532
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003533 if (context->hasActiveTransformFeedback(program))
3534 {
3535 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003536 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003537 "Cannot change program binary while program is associated with "
3538 "an active transform feedback object."));
3539 return false;
3540 }
3541
Geoff Langc5629752015-12-07 16:29:04 -05003542 return true;
3543}
3544
3545bool ValidateGetProgramBinaryBase(Context *context,
3546 GLuint program,
3547 GLsizei bufSize,
3548 GLsizei *length,
3549 GLenum *binaryFormat,
3550 void *binary)
3551{
3552 Program *programObject = GetValidProgram(context, program);
3553 if (programObject == nullptr)
3554 {
3555 return false;
3556 }
3557
3558 if (!programObject->isLinked())
3559 {
Jamie Madill437fa652016-05-03 15:13:24 -04003560 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05003561 return false;
3562 }
3563
3564 return true;
3565}
Jamie Madillc29968b2016-01-20 11:17:23 -05003566
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003567bool ValidateUseProgram(Context *context, GLuint program)
3568{
3569 if (program != 0)
3570 {
3571 Program *programObject = context->getProgram(program);
3572 if (!programObject)
3573 {
3574 // ES 3.1.0 section 7.3 page 72
3575 if (context->getShader(program))
3576 {
Jamie Madill437fa652016-05-03 15:13:24 -04003577 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003578 Error(GL_INVALID_OPERATION,
3579 "Attempted to use a single shader instead of a shader program."));
3580 return false;
3581 }
3582 else
3583 {
Jamie Madill437fa652016-05-03 15:13:24 -04003584 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003585 return false;
3586 }
3587 }
3588 if (!programObject->isLinked())
3589 {
Jamie Madill437fa652016-05-03 15:13:24 -04003590 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003591 return false;
3592 }
3593 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003594 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003595 {
3596 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003597 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003598 Error(GL_INVALID_OPERATION,
3599 "Cannot change active program while transform feedback is unpaused."));
3600 return false;
3601 }
3602
3603 return true;
3604}
3605
Jamie Madillc29968b2016-01-20 11:17:23 -05003606bool ValidateCopyTexImage2D(ValidationContext *context,
3607 GLenum target,
3608 GLint level,
3609 GLenum internalformat,
3610 GLint x,
3611 GLint y,
3612 GLsizei width,
3613 GLsizei height,
3614 GLint border)
3615{
Martin Radev1be913c2016-07-11 17:59:16 +03003616 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003617 {
3618 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
3619 0, x, y, width, height, border);
3620 }
3621
Martin Radev1be913c2016-07-11 17:59:16 +03003622 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003623 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
3624 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003625}
Jamie Madillc29968b2016-01-20 11:17:23 -05003626
3627bool ValidateFramebufferRenderbuffer(Context *context,
3628 GLenum target,
3629 GLenum attachment,
3630 GLenum renderbuffertarget,
3631 GLuint renderbuffer)
3632{
3633 if (!ValidFramebufferTarget(target) ||
3634 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
3635 {
Jamie Madill437fa652016-05-03 15:13:24 -04003636 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05003637 return false;
3638 }
3639
3640 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
3641 renderbuffertarget, renderbuffer);
3642}
3643
3644bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3645{
3646 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3647 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3648 {
Jamie Madill437fa652016-05-03 15:13:24 -04003649 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003650 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
3651 return false;
3652 }
3653
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003654 ASSERT(context->getGLState().getDrawFramebuffer());
3655 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003656 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3657
3658 // This should come first before the check for the default frame buffer
3659 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3660 // rather than INVALID_OPERATION
3661 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3662 {
3663 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3664
3665 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003666 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3667 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003668 {
3669 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003670 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3671 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3672 // 3.1 is still a bit ambiguous about the error, but future specs are
3673 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04003674 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02003675 return false;
3676 }
3677 else if (bufs[colorAttachment] >= maxColorAttachment)
3678 {
Jamie Madill437fa652016-05-03 15:13:24 -04003679 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02003680 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05003681 return false;
3682 }
3683 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3684 frameBufferId != 0)
3685 {
3686 // INVALID_OPERATION-GL is bound to buffer and ith argument
3687 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04003688 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05003689 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
3690 return false;
3691 }
3692 }
3693
3694 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3695 // and n is not 1 or bufs is bound to value other than BACK and NONE
3696 if (frameBufferId == 0)
3697 {
3698 if (n != 1)
3699 {
Jamie Madill437fa652016-05-03 15:13:24 -04003700 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05003701 "n must be 1 when GL is bound to the default framebuffer"));
3702 return false;
3703 }
3704
3705 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3706 {
Jamie Madill437fa652016-05-03 15:13:24 -04003707 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05003708 GL_INVALID_OPERATION,
3709 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
3710 return false;
3711 }
3712 }
3713
3714 return true;
3715}
3716
3717bool ValidateCopyTexSubImage2D(Context *context,
3718 GLenum target,
3719 GLint level,
3720 GLint xoffset,
3721 GLint yoffset,
3722 GLint x,
3723 GLint y,
3724 GLsizei width,
3725 GLsizei height)
3726{
Martin Radev1be913c2016-07-11 17:59:16 +03003727 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05003728 {
3729 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
3730 yoffset, x, y, width, height, 0);
3731 }
3732
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05003733 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
3734 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05003735}
3736
Olli Etuaho4f667482016-03-30 15:56:35 +03003737bool ValidateGetBufferPointervBase(Context *context, GLenum target, GLenum pname, void **params)
3738{
3739 if (!ValidBufferTarget(context, target))
3740 {
Jamie Madill437fa652016-05-03 15:13:24 -04003741 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03003742 return false;
3743 }
3744
3745 if (pname != GL_BUFFER_MAP_POINTER)
3746 {
Jamie Madill437fa652016-05-03 15:13:24 -04003747 context->handleError(Error(GL_INVALID_ENUM, "pname not valid: 0x%X", pname));
Olli Etuaho4f667482016-03-30 15:56:35 +03003748 return false;
3749 }
3750
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003751 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003752
3753 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3754 // target bound to zero generate an INVALID_OPERATION error."
3755 // GLES 3.1 section 6.6 explicitly specifies this error.
3756 if (!buffer)
3757 {
Jamie Madill437fa652016-05-03 15:13:24 -04003758 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003759 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
3760 return false;
3761 }
3762
3763 return true;
3764}
3765
3766bool ValidateUnmapBufferBase(Context *context, GLenum target)
3767{
3768 if (!ValidBufferTarget(context, target))
3769 {
Jamie Madill437fa652016-05-03 15:13:24 -04003770 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003771 return false;
3772 }
3773
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003774 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003775
3776 if (buffer == nullptr || !buffer->isMapped())
3777 {
Jamie Madill437fa652016-05-03 15:13:24 -04003778 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003779 return false;
3780 }
3781
3782 return true;
3783}
3784
3785bool ValidateMapBufferRangeBase(Context *context,
3786 GLenum target,
3787 GLintptr offset,
3788 GLsizeiptr length,
3789 GLbitfield access)
3790{
3791 if (!ValidBufferTarget(context, target))
3792 {
Jamie Madill437fa652016-05-03 15:13:24 -04003793 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003794 return false;
3795 }
3796
3797 if (offset < 0 || length < 0)
3798 {
Jamie Madill437fa652016-05-03 15:13:24 -04003799 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003800 return false;
3801 }
3802
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003803 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003804
3805 if (!buffer)
3806 {
Jamie Madill437fa652016-05-03 15:13:24 -04003807 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003808 return false;
3809 }
3810
3811 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003812 CheckedNumeric<size_t> checkedOffset(offset);
3813 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003814
Jamie Madille2e406c2016-06-02 13:04:10 -04003815 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003816 {
Jamie Madill437fa652016-05-03 15:13:24 -04003817 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003818 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
3819 return false;
3820 }
3821
3822 // Check for invalid bits in the mask
3823 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3824 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3825 GL_MAP_UNSYNCHRONIZED_BIT;
3826
3827 if (access & ~(allAccessBits))
3828 {
Jamie Madill437fa652016-05-03 15:13:24 -04003829 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03003830 return false;
3831 }
3832
3833 if (length == 0)
3834 {
Jamie Madill437fa652016-05-03 15:13:24 -04003835 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003836 return false;
3837 }
3838
3839 if (buffer->isMapped())
3840 {
Jamie Madill437fa652016-05-03 15:13:24 -04003841 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003842 return false;
3843 }
3844
3845 // Check for invalid bit combinations
3846 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3847 {
Jamie Madill437fa652016-05-03 15:13:24 -04003848 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003849 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
3850 return false;
3851 }
3852
3853 GLbitfield writeOnlyBits =
3854 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3855
3856 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3857 {
Jamie Madill437fa652016-05-03 15:13:24 -04003858 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03003859 "Invalid access bits when mapping buffer for reading: 0x%X.",
3860 access));
3861 return false;
3862 }
3863
3864 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3865 {
Jamie Madill437fa652016-05-03 15:13:24 -04003866 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003867 GL_INVALID_OPERATION,
3868 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
3869 return false;
3870 }
3871 return true;
3872}
3873
3874bool ValidateFlushMappedBufferRangeBase(Context *context,
3875 GLenum target,
3876 GLintptr offset,
3877 GLsizeiptr length)
3878{
3879 if (offset < 0 || length < 0)
3880 {
Jamie Madill437fa652016-05-03 15:13:24 -04003881 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003882 return false;
3883 }
3884
3885 if (!ValidBufferTarget(context, target))
3886 {
Jamie Madill437fa652016-05-03 15:13:24 -04003887 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003888 return false;
3889 }
3890
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003891 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003892
3893 if (buffer == nullptr)
3894 {
Jamie Madill437fa652016-05-03 15:13:24 -04003895 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03003896 return false;
3897 }
3898
3899 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3900 {
Jamie Madill437fa652016-05-03 15:13:24 -04003901 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03003902 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
3903 return false;
3904 }
3905
3906 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003907 CheckedNumeric<size_t> checkedOffset(offset);
3908 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003909
Jamie Madille2e406c2016-06-02 13:04:10 -04003910 if (!checkedSize.IsValid() ||
3911 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003912 {
Jamie Madill437fa652016-05-03 15:13:24 -04003913 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03003914 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
3915 return false;
3916 }
3917
3918 return true;
3919}
3920
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003921bool ValidateGenerateMipmap(Context *context, GLenum target)
3922{
3923 if (!ValidTextureTarget(context, target))
3924 {
3925 context->handleError(Error(GL_INVALID_ENUM));
3926 return false;
3927 }
3928
3929 Texture *texture = context->getTargetTexture(target);
3930
3931 if (texture == nullptr)
3932 {
3933 context->handleError(Error(GL_INVALID_OPERATION));
3934 return false;
3935 }
3936
3937 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
3938
3939 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
3940 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
3941 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
3942 {
3943 context->handleError(Error(GL_INVALID_OPERATION));
3944 return false;
3945 }
3946
Jamie Madilla3944d42016-07-22 22:13:26 -04003947 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
3948 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
3949 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003950
3951 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
3952 // unsized formats or that are color renderable and filterable. Since we do not track if
3953 // the texture was created with sized or unsized format (only sized formats are stored),
3954 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
3955 // be able to) because they aren't color renderable. Simply do a special case for LUMA
3956 // textures since they're the only texture format that can be created with unsized formats
3957 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
3958 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04003959 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
3960 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003961 {
3962 context->handleError(Error(GL_INVALID_OPERATION));
3963 return false;
3964 }
3965
3966 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04003967 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003968 {
3969 context->handleError(Error(GL_INVALID_OPERATION));
3970 return false;
3971 }
3972
3973 // Non-power of 2 ES2 check
3974 if (!context->getExtensions().textureNPOT &&
3975 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
3976 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
3977 {
Martin Radev1be913c2016-07-11 17:59:16 +03003978 ASSERT(context->getClientMajorVersion() <= 2 &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03003979 (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
3980 context->handleError(Error(GL_INVALID_OPERATION));
3981 return false;
3982 }
3983
3984 // Cube completeness check
3985 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
3986 {
3987 context->handleError(Error(GL_INVALID_OPERATION));
3988 return false;
3989 }
3990
3991 return true;
3992}
3993
Olli Etuaho41997e72016-03-10 13:38:39 +02003994bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
3995{
3996 return ValidateGenOrDelete(context, n);
3997}
3998
3999bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4000{
4001 return ValidateGenOrDelete(context, n);
4002}
4003
4004bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4005{
4006 return ValidateGenOrDelete(context, n);
4007}
4008
4009bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4010{
4011 return ValidateGenOrDelete(context, n);
4012}
4013
4014bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4015{
4016 return ValidateGenOrDelete(context, n);
4017}
4018
4019bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4020{
4021 return ValidateGenOrDelete(context, n);
4022}
4023
4024bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4025{
4026 return ValidateGenOrDelete(context, n);
4027}
4028
4029bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4030{
4031 return ValidateGenOrDelete(context, n);
4032}
4033
4034bool ValidateGenOrDelete(Context *context, GLint n)
4035{
4036 if (n < 0)
4037 {
Jamie Madill437fa652016-05-03 15:13:24 -04004038 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004039 return false;
4040 }
4041 return true;
4042}
4043
Geoff Langf41a7152016-09-19 15:11:17 -04004044bool ValidateEnable(Context *context, GLenum cap)
4045{
4046 if (!ValidCap(context, cap, false))
4047 {
4048 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4049 return false;
4050 }
4051
4052 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4053 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4054 {
4055 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4056 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4057
4058 // We also output an error message to the debugger window if tracing is active, so that
4059 // developers can see the error message.
4060 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004061 return false;
4062 }
4063
4064 return true;
4065}
4066
4067bool ValidateDisable(Context *context, GLenum cap)
4068{
4069 if (!ValidCap(context, cap, false))
4070 {
4071 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4072 return false;
4073 }
4074
4075 return true;
4076}
4077
4078bool ValidateIsEnabled(Context *context, GLenum cap)
4079{
4080 if (!ValidCap(context, cap, true))
4081 {
4082 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4083 return false;
4084 }
4085
4086 return true;
4087}
4088
Geoff Langff5b2d52016-09-07 11:32:23 -04004089bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4090{
4091 if (!context->getExtensions().robustClientMemory)
4092 {
4093 context->handleError(
4094 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4095 return false;
4096 }
4097
4098 if (bufSize < 0)
4099 {
4100 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4101 return false;
4102 }
4103
4104 return true;
4105}
4106
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004107bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4108{
4109 if (bufSize < numParams)
4110 {
4111 context->handleError(Error(GL_INVALID_OPERATION,
4112 "%u parameters are required but %i were provided.", numParams,
4113 bufSize));
4114 return false;
4115 }
4116
4117 return true;
4118}
4119
Geoff Langff5b2d52016-09-07 11:32:23 -04004120bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4121 GLenum target,
4122 GLenum attachment,
4123 GLenum pname,
4124 GLsizei *numParams)
4125{
4126 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4127 *numParams = 1;
4128
4129 if (!ValidFramebufferTarget(target))
4130 {
4131 context->handleError(Error(GL_INVALID_ENUM));
4132 return false;
4133 }
4134
4135 int clientVersion = context->getClientMajorVersion();
4136
4137 switch (pname)
4138 {
4139 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4140 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4141 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4142 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4143 break;
4144
4145 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4146 if (clientVersion < 3 && !context->getExtensions().sRGB)
4147 {
4148 context->handleError(Error(GL_INVALID_ENUM));
4149 return false;
4150 }
4151 break;
4152
4153 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4154 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4155 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4156 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4157 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4158 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4159 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4160 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4161 if (clientVersion < 3)
4162 {
4163 context->handleError(Error(GL_INVALID_ENUM));
4164 return false;
4165 }
4166 break;
4167
4168 default:
4169 context->handleError(Error(GL_INVALID_ENUM));
4170 return false;
4171 }
4172
4173 // Determine if the attachment is a valid enum
4174 switch (attachment)
4175 {
4176 case GL_BACK:
4177 case GL_FRONT:
4178 case GL_DEPTH:
4179 case GL_STENCIL:
4180 case GL_DEPTH_STENCIL_ATTACHMENT:
4181 if (clientVersion < 3)
4182 {
4183 context->handleError(Error(GL_INVALID_ENUM));
4184 return false;
4185 }
4186 break;
4187
4188 case GL_DEPTH_ATTACHMENT:
4189 case GL_STENCIL_ATTACHMENT:
4190 break;
4191
4192 default:
4193 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4194 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4195 {
4196 context->handleError(Error(GL_INVALID_ENUM));
4197 return false;
4198 }
4199 break;
4200 }
4201
4202 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4203 ASSERT(framebuffer);
4204
4205 if (framebuffer->id() == 0)
4206 {
4207 if (clientVersion < 3)
4208 {
4209 context->handleError(Error(GL_INVALID_OPERATION));
4210 return false;
4211 }
4212
4213 switch (attachment)
4214 {
4215 case GL_BACK:
4216 case GL_DEPTH:
4217 case GL_STENCIL:
4218 break;
4219
4220 default:
4221 context->handleError(Error(GL_INVALID_OPERATION));
4222 return false;
4223 }
4224 }
4225 else
4226 {
4227 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4228 {
4229 // Valid attachment query
4230 }
4231 else
4232 {
4233 switch (attachment)
4234 {
4235 case GL_DEPTH_ATTACHMENT:
4236 case GL_STENCIL_ATTACHMENT:
4237 break;
4238
4239 case GL_DEPTH_STENCIL_ATTACHMENT:
4240 if (!framebuffer->hasValidDepthStencil())
4241 {
4242 context->handleError(Error(GL_INVALID_OPERATION));
4243 return false;
4244 }
4245 break;
4246
4247 default:
4248 context->handleError(Error(GL_INVALID_OPERATION));
4249 return false;
4250 }
4251 }
4252 }
4253
4254 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4255 if (attachmentObject)
4256 {
4257 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4258 attachmentObject->type() == GL_TEXTURE ||
4259 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4260
4261 switch (pname)
4262 {
4263 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4264 if (attachmentObject->type() != GL_RENDERBUFFER &&
4265 attachmentObject->type() != GL_TEXTURE)
4266 {
4267 context->handleError(Error(GL_INVALID_ENUM));
4268 return false;
4269 }
4270 break;
4271
4272 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4273 if (attachmentObject->type() != GL_TEXTURE)
4274 {
4275 context->handleError(Error(GL_INVALID_ENUM));
4276 return false;
4277 }
4278 break;
4279
4280 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4281 if (attachmentObject->type() != GL_TEXTURE)
4282 {
4283 context->handleError(Error(GL_INVALID_ENUM));
4284 return false;
4285 }
4286 break;
4287
4288 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4289 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4290 {
4291 context->handleError(Error(GL_INVALID_OPERATION));
4292 return false;
4293 }
4294 break;
4295
4296 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4297 if (attachmentObject->type() != GL_TEXTURE)
4298 {
4299 context->handleError(Error(GL_INVALID_ENUM));
4300 return false;
4301 }
4302 break;
4303
4304 default:
4305 break;
4306 }
4307 }
4308 else
4309 {
4310 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4311 // is NONE, then querying any other pname will generate INVALID_ENUM.
4312
4313 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4314 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4315 // INVALID_OPERATION for all other pnames
4316
4317 switch (pname)
4318 {
4319 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4320 break;
4321
4322 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4323 if (clientVersion < 3)
4324 {
4325 context->handleError(Error(GL_INVALID_ENUM));
4326 return false;
4327 }
4328 break;
4329
4330 default:
4331 if (clientVersion < 3)
4332 {
4333 context->handleError(Error(GL_INVALID_ENUM));
4334 return false;
4335 }
4336 else
4337 {
4338 context->handleError(Error(GL_INVALID_OPERATION));
4339 return false;
4340 }
4341 }
4342 }
4343
4344 return true;
4345}
4346
4347bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4348 GLenum target,
4349 GLenum attachment,
4350 GLenum pname,
4351 GLsizei bufSize,
4352 GLsizei *numParams)
4353{
4354 if (!ValidateRobustEntryPoint(context, bufSize))
4355 {
4356 return false;
4357 }
4358
4359 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4360 {
4361 return false;
4362 }
4363
4364 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4365 {
4366 return false;
4367 }
4368
4369 return true;
4370}
4371
4372bool ValidateGetBufferParameteriv(ValidationContext *context,
4373 GLenum target,
4374 GLenum pname,
4375 GLsizei *numParams)
4376{
4377 // Initialize result
4378 *numParams = 0;
4379
4380 if (!ValidBufferTarget(context, target))
4381 {
4382 context->handleError(Error(GL_INVALID_ENUM));
4383 return false;
4384 }
4385
4386 if (!ValidBufferParameter(context, pname, numParams))
4387 {
4388 context->handleError(Error(GL_INVALID_ENUM));
4389 return false;
4390 }
4391
4392 if (context->getGLState().getTargetBuffer(target) == nullptr)
4393 {
4394 // A null buffer means that "0" is bound to the requested buffer target
4395 context->handleError(Error(GL_INVALID_OPERATION));
4396 return false;
4397 }
4398
4399 return true;
4400}
4401
4402bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4403 GLenum target,
4404 GLenum pname,
4405 GLsizei bufSize,
4406 GLsizei *numParams)
4407{
4408 if (!ValidateRobustEntryPoint(context, bufSize))
4409 {
4410 return false;
4411 }
4412
4413 if (!ValidateGetBufferParameteriv(context, target, pname, numParams))
4414 {
4415 return false;
4416 }
4417
4418 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4419 {
4420 return false;
4421 }
4422
4423 return true;
4424}
4425
4426bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4427{
4428 // Currently, all GetProgramiv queries return 1 parameter
4429 *numParams = 1;
4430
4431 Program *programObject = GetValidProgram(context, program);
4432 if (!programObject)
4433 {
4434 return false;
4435 }
4436
4437 switch (pname)
4438 {
4439 case GL_DELETE_STATUS:
4440 case GL_LINK_STATUS:
4441 case GL_VALIDATE_STATUS:
4442 case GL_INFO_LOG_LENGTH:
4443 case GL_ATTACHED_SHADERS:
4444 case GL_ACTIVE_ATTRIBUTES:
4445 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4446 case GL_ACTIVE_UNIFORMS:
4447 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4448 break;
4449
4450 case GL_PROGRAM_BINARY_LENGTH:
4451 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4452 {
4453 context->handleError(Error(GL_INVALID_ENUM,
4454 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4455 "GL_OES_get_program_binary or ES 3.0."));
4456 return false;
4457 }
4458 break;
4459
4460 case GL_ACTIVE_UNIFORM_BLOCKS:
4461 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4462 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4463 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4464 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4465 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4466 if (context->getClientMajorVersion() < 3)
4467 {
4468 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4469 return false;
4470 }
4471 break;
4472
4473 default:
4474 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4475 return false;
4476 }
4477
4478 return true;
4479}
4480
4481bool ValidateGetProgramivRobustANGLE(Context *context,
4482 GLuint program,
4483 GLenum pname,
4484 GLsizei bufSize,
4485 GLsizei *numParams)
4486{
4487 if (!ValidateRobustEntryPoint(context, bufSize))
4488 {
4489 return false;
4490 }
4491
4492 if (!ValidateGetProgramiv(context, program, pname, numParams))
4493 {
4494 return false;
4495 }
4496
4497 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4498 {
4499 return false;
4500 }
4501
4502 return true;
4503}
4504
Geoff Lang740d9022016-10-07 11:20:52 -04004505bool ValidateGetRenderbufferParameteriv(Context *context,
4506 GLenum target,
4507 GLenum pname,
4508 GLint *params)
4509{
4510 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4511}
4512
4513bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4514 GLenum target,
4515 GLenum pname,
4516 GLsizei bufSize,
4517 GLsizei *length,
4518 GLint *params)
4519{
4520 if (!ValidateRobustEntryPoint(context, bufSize))
4521 {
4522 return false;
4523 }
4524
4525 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4526 {
4527 return false;
4528 }
4529
4530 if (!ValidateRobustBufferSize(context, bufSize, *length))
4531 {
4532 return false;
4533 }
4534
4535 return true;
4536}
4537
Geoff Langd7d0ed32016-10-07 11:33:51 -04004538bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
4539{
4540 return ValidateGetShaderivBase(context, shader, pname, nullptr);
4541}
4542
4543bool ValidateGetShaderivRobustANGLE(Context *context,
4544 GLuint shader,
4545 GLenum pname,
4546 GLsizei bufSize,
4547 GLsizei *length,
4548 GLint *params)
4549{
4550 if (!ValidateRobustEntryPoint(context, bufSize))
4551 {
4552 return false;
4553 }
4554
4555 if (!ValidateGetShaderivBase(context, shader, pname, length))
4556 {
4557 return false;
4558 }
4559
4560 if (!ValidateRobustBufferSize(context, bufSize, *length))
4561 {
4562 return false;
4563 }
4564
4565 return true;
4566}
4567
Geoff Langc1984ed2016-10-07 12:41:00 -04004568bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
4569{
4570 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4571}
4572
4573bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4574 GLenum target,
4575 GLenum pname,
4576 GLsizei bufSize,
4577 GLsizei *length,
4578 GLfloat *params)
4579{
4580 if (!ValidateRobustEntryPoint(context, bufSize))
4581 {
4582 return false;
4583 }
4584
4585 if (!ValidateGetTexParameterBase(context, target, pname, length))
4586 {
4587 return false;
4588 }
4589
4590 if (!ValidateRobustBufferSize(context, bufSize, *length))
4591 {
4592 return false;
4593 }
4594
4595 return true;
4596}
4597
4598bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
4599{
4600 return ValidateGetTexParameterBase(context, target, pname, nullptr);
4601}
4602
4603bool ValidateGetTexParameterivRobustANGLE(Context *context,
4604 GLenum target,
4605 GLenum pname,
4606 GLsizei bufSize,
4607 GLsizei *length,
4608 GLint *params)
4609{
4610 if (!ValidateRobustEntryPoint(context, bufSize))
4611 {
4612 return false;
4613 }
4614
4615 if (!ValidateGetTexParameterBase(context, target, pname, length))
4616 {
4617 return false;
4618 }
4619
4620 if (!ValidateRobustBufferSize(context, bufSize, *length))
4621 {
4622 return false;
4623 }
4624
4625 return true;
4626}
4627
4628bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
4629{
4630 return ValidateTexParameterBase(context, target, pname, -1, &param);
4631}
4632
4633bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
4634{
4635 return ValidateTexParameterBase(context, target, pname, -1, params);
4636}
4637
4638bool ValidateTexParameterfvRobustANGLE(Context *context,
4639 GLenum target,
4640 GLenum pname,
4641 GLsizei bufSize,
4642 const GLfloat *params)
4643{
4644 if (!ValidateRobustEntryPoint(context, bufSize))
4645 {
4646 return false;
4647 }
4648
4649 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4650}
4651
4652bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
4653{
4654 return ValidateTexParameterBase(context, target, pname, -1, &param);
4655}
4656
4657bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
4658{
4659 return ValidateTexParameterBase(context, target, pname, -1, params);
4660}
4661
4662bool ValidateTexParameterivRobustANGLE(Context *context,
4663 GLenum target,
4664 GLenum pname,
4665 GLsizei bufSize,
4666 const GLint *params)
4667{
4668 if (!ValidateRobustEntryPoint(context, bufSize))
4669 {
4670 return false;
4671 }
4672
4673 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4674}
4675
4676bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4677{
4678 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4679}
4680
4681bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4682 GLuint sampler,
4683 GLenum pname,
4684 GLuint bufSize,
4685 GLsizei *length,
4686 GLfloat *params)
4687{
4688 if (!ValidateRobustEntryPoint(context, bufSize))
4689 {
4690 return false;
4691 }
4692
4693 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4694 {
4695 return false;
4696 }
4697
4698 if (!ValidateRobustBufferSize(context, bufSize, *length))
4699 {
4700 return false;
4701 }
4702
4703 return true;
4704}
4705
4706bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4707{
4708 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4709}
4710
4711bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4712 GLuint sampler,
4713 GLenum pname,
4714 GLuint bufSize,
4715 GLsizei *length,
4716 GLint *params)
4717{
4718 if (!ValidateRobustEntryPoint(context, bufSize))
4719 {
4720 return false;
4721 }
4722
4723 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4724 {
4725 return false;
4726 }
4727
4728 if (!ValidateRobustBufferSize(context, bufSize, *length))
4729 {
4730 return false;
4731 }
4732
4733 return true;
4734}
4735
4736bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4737{
4738 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4739}
4740
4741bool ValidateSamplerParameterfv(Context *context,
4742 GLuint sampler,
4743 GLenum pname,
4744 const GLfloat *params)
4745{
4746 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4747}
4748
4749bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4750 GLuint sampler,
4751 GLenum pname,
4752 GLsizei bufSize,
4753 const GLfloat *params)
4754{
4755 if (!ValidateRobustEntryPoint(context, bufSize))
4756 {
4757 return false;
4758 }
4759
4760 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4761}
4762
4763bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4764{
4765 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4766}
4767
4768bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4769{
4770 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4771}
4772
4773bool ValidateSamplerParameterivRobustANGLE(Context *context,
4774 GLuint sampler,
4775 GLenum pname,
4776 GLsizei bufSize,
4777 const GLint *params)
4778{
4779 if (!ValidateRobustEntryPoint(context, bufSize))
4780 {
4781 return false;
4782 }
4783
4784 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4785}
4786
Geoff Lang0b031062016-10-13 14:30:04 -04004787bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
4788{
4789 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
4790}
4791
4792bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4793 GLuint index,
4794 GLenum pname,
4795 GLsizei bufSize,
4796 GLsizei *length,
4797 GLfloat *params)
4798{
4799 if (!ValidateRobustEntryPoint(context, bufSize))
4800 {
4801 return false;
4802 }
4803
4804 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4805 {
4806 return false;
4807 }
4808
4809 if (!ValidateRobustBufferSize(context, bufSize, *length))
4810 {
4811 return false;
4812 }
4813
4814 return true;
4815}
4816
4817bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
4818{
4819 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
4820}
4821
4822bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4823 GLuint index,
4824 GLenum pname,
4825 GLsizei bufSize,
4826 GLsizei *length,
4827 GLint *params)
4828{
4829 if (!ValidateRobustEntryPoint(context, bufSize))
4830 {
4831 return false;
4832 }
4833
4834 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4835 {
4836 return false;
4837 }
4838
4839 if (!ValidateRobustBufferSize(context, bufSize, *length))
4840 {
4841 return false;
4842 }
4843
4844 return true;
4845}
4846
4847bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
4848{
4849 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
4850}
4851
4852bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4853 GLuint index,
4854 GLenum pname,
4855 GLsizei bufSize,
4856 GLsizei *length,
4857 void **pointer)
4858{
4859 if (!ValidateRobustEntryPoint(context, bufSize))
4860 {
4861 return false;
4862 }
4863
4864 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4865 {
4866 return false;
4867 }
4868
4869 if (!ValidateRobustBufferSize(context, bufSize, *length))
4870 {
4871 return false;
4872 }
4873
4874 return true;
4875}
4876
4877bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4878{
4879 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4880}
4881
4882bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4883 GLuint index,
4884 GLenum pname,
4885 GLsizei bufSize,
4886 GLsizei *length,
4887 GLint *params)
4888{
4889 if (!ValidateRobustEntryPoint(context, bufSize))
4890 {
4891 return false;
4892 }
4893
4894 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4895 {
4896 return false;
4897 }
4898
4899 if (!ValidateRobustBufferSize(context, bufSize, *length))
4900 {
4901 return false;
4902 }
4903
4904 return true;
4905}
4906
4907bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4908{
4909 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4910}
4911
4912bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4913 GLuint index,
4914 GLenum pname,
4915 GLsizei bufSize,
4916 GLsizei *length,
4917 GLuint *params)
4918{
4919 if (!ValidateRobustEntryPoint(context, bufSize))
4920 {
4921 return false;
4922 }
4923
4924 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4925 {
4926 return false;
4927 }
4928
4929 if (!ValidateRobustBufferSize(context, bufSize, *length))
4930 {
4931 return false;
4932 }
4933
4934 return true;
4935}
4936
Jamie Madillc29968b2016-01-20 11:17:23 -05004937} // namespace gl