blob: aabc42f611f45e5dec30ac4e9c9f4024d23bf6d3 [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{
Corentin Wallez92db6942016-12-09 13:10:36 -050037bool ValidateDrawAttribs(ValidationContext *context,
38 GLint primcount,
39 GLint maxVertex,
40 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040041{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070042 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040043 const gl::Program *program = state.getProgram();
44
Corentin Wallez327411e2016-12-09 11:09:17 -050045 bool webglCompatibility = context->getExtensions().webglCompatibility;
46
He Yunchaoced53ae2016-11-29 15:00:51 +080047 const VertexArray *vao = state.getVertexArray();
48 const auto &vertexAttribs = vao->getVertexAttributes();
49 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040050 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
51 {
52 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallezfd456442016-12-21 17:57:00 -050053 if (!program->isAttribLocationActive(attributeIndex) || !attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040054 {
Corentin Wallezfd456442016-12-21 17:57:00 -050055 continue;
56 }
Jamie Madill1ca74672015-07-21 15:14:11 -040057
Corentin Wallezfd456442016-12-21 17:57:00 -050058 // If we have no buffer, then we either get an error, or there are no more checks to be done.
59 gl::Buffer *buffer = attrib.buffer.get();
60 if (!buffer)
61 {
Geoff Langfeb8c682017-02-13 16:07:35 -050062 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050063 {
64 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050065 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
66 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
67 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
68 // error.
Corentin Wallez327411e2016-12-09 11:09:17 -050069 context->handleError(
70 Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer."));
Corentin Wallezfd456442016-12-21 17:57:00 -050071 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050072 }
Corentin Wallezfd456442016-12-21 17:57:00 -050073 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040074 {
75 // This is an application error that would normally result in a crash,
76 // but we catch it and return an error
Corentin Wallezfd456442016-12-21 17:57:00 -050077 context->handleError(
78 Error(GL_INVALID_OPERATION,
79 "An enabled vertex array has no buffer and no pointer."));
Jamie Madill1ca74672015-07-21 15:14:11 -040080 return false;
81 }
Corentin Wallezfd456442016-12-21 17:57:00 -050082 continue;
83 }
84
85 // If we're drawing zero vertices, we have enough data.
86 if (vertexCount <= 0 || primcount <= 0)
87 {
88 continue;
89 }
90
91 GLint maxVertexElement = 0;
92 if (attrib.divisor == 0)
93 {
94 maxVertexElement = maxVertex;
95 }
96 else
97 {
98 maxVertexElement = (primcount - 1) / attrib.divisor;
99 }
100
101 // We do manual overflow checks here instead of using safe_math.h because it was
102 // a bottleneck. Thanks to some properties of GL we know inequalities that can
103 // help us make the overflow checks faster.
104
105 // The max possible attribSize is 16 for a vector of 4 32 bit values.
106 constexpr uint64_t kMaxAttribSize = 16;
107 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
108 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
109
110 // We know attribStride is given as a GLsizei which is typedefed to int.
111 // We also know an upper bound for attribSize.
112 static_assert(std::is_same<int, GLsizei>::value, "");
113 uint64_t attribStride = ComputeVertexAttributeStride(attrib);
114 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
115 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
116
117 // Computing the max offset using uint64_t without attrib.offset is overflow
118 // safe. Note: Last vertex element does not take the full stride!
119 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
120 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
121
122 // An overflow can happen when adding the offset, check for it.
123 uint64_t attribOffset = attrib.offset;
124 if (attribDataSizeNoOffset > kUint64Max - attrib.offset)
125 {
126 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
127 return false;
128 }
129 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
130
131 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
132 // We can return INVALID_OPERATION if our vertex attribute does not have
133 // enough backing data.
134 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
135 {
136 context->handleError(Error(GL_INVALID_OPERATION,
137 "Vertex buffer is not big enough for the draw call"));
138 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400139 }
140 }
141
142 return true;
143}
144
Geoff Langf607c602016-09-21 11:46:48 -0400145bool ValidReadPixelsFormatType(ValidationContext *context,
146 GLenum framebufferComponentType,
147 GLenum format,
148 GLenum type)
149{
150 switch (framebufferComponentType)
151 {
152 case GL_UNSIGNED_NORMALIZED:
153 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
154 // ReadPixels with BGRA even if the extension is not present
155 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
156 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
157 type == GL_UNSIGNED_BYTE);
158
159 case GL_SIGNED_NORMALIZED:
160 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
161
162 case GL_INT:
163 return (format == GL_RGBA_INTEGER && type == GL_INT);
164
165 case GL_UNSIGNED_INT:
166 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
167
168 case GL_FLOAT:
169 return (format == GL_RGBA && type == GL_FLOAT);
170
171 default:
172 UNREACHABLE();
173 return false;
174 }
175}
176
Geoff Langf41a7152016-09-19 15:11:17 -0400177bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500178{
179 switch (cap)
180 {
Geoff Langf41a7152016-09-19 15:11:17 -0400181 // EXT_multisample_compatibility
182 case GL_MULTISAMPLE_EXT:
183 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
184 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300185
Geoff Langf41a7152016-09-19 15:11:17 -0400186 case GL_CULL_FACE:
187 case GL_POLYGON_OFFSET_FILL:
188 case GL_SAMPLE_ALPHA_TO_COVERAGE:
189 case GL_SAMPLE_COVERAGE:
190 case GL_SCISSOR_TEST:
191 case GL_STENCIL_TEST:
192 case GL_DEPTH_TEST:
193 case GL_BLEND:
194 case GL_DITHER:
195 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500196
Geoff Langf41a7152016-09-19 15:11:17 -0400197 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
198 case GL_RASTERIZER_DISCARD:
199 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500200
Geoff Langf41a7152016-09-19 15:11:17 -0400201 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
202 case GL_DEBUG_OUTPUT:
203 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500204
Geoff Langf41a7152016-09-19 15:11:17 -0400205 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
206 return queryOnly && context->getExtensions().bindGeneratesResource;
207
Geoff Langfeb8c682017-02-13 16:07:35 -0500208 case GL_CLIENT_ARRAYS_ANGLE:
209 return queryOnly && context->getExtensions().clientArrays;
210
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700211 case GL_FRAMEBUFFER_SRGB_EXT:
212 return context->getExtensions().sRGBWriteControl;
213
Geoff Lang3b573612016-10-31 14:08:10 -0400214 case GL_SAMPLE_MASK:
Geoff Lang3b573612016-10-31 14:08:10 -0400215 return context->getClientVersion() >= Version(3, 1);
216
Geoff Langf41a7152016-09-19 15:11:17 -0400217 default:
218 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500219 }
220}
221
Geoff Lang62fce5b2016-09-30 10:46:35 -0400222bool ValidateReadPixelsBase(ValidationContext *context,
223 GLint x,
224 GLint y,
225 GLsizei width,
226 GLsizei height,
227 GLenum format,
228 GLenum type,
229 GLsizei bufSize,
230 GLsizei *length,
231 GLvoid *pixels)
232{
233 if (length != nullptr)
234 {
235 *length = 0;
236 }
237
238 if (width < 0 || height < 0)
239 {
240 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
241 return false;
242 }
243
244 auto readFramebuffer = context->getGLState().getReadFramebuffer();
245
246 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
247 {
248 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
249 return false;
250 }
251
252 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
253 {
254 context->handleError(Error(GL_INVALID_OPERATION));
255 return false;
256 }
257
258 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
259 ASSERT(framebuffer);
260
261 if (framebuffer->getReadBufferState() == GL_NONE)
262 {
263 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
264 return false;
265 }
266
267 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500268 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
269 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
270 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
271 // situation is an application error that would lead to a crash in ANGLE.
272 if (readBuffer == nullptr)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400273 {
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500274 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
Geoff Lang62fce5b2016-09-30 10:46:35 -0400275 return false;
276 }
277
278 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
279 GLenum currentType = framebuffer->getImplementationColorReadType();
280 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
281
282 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
283 bool validFormatTypeCombination =
284 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
285
286 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
287 {
288 context->handleError(Error(GL_INVALID_OPERATION));
289 return false;
290 }
291
292 // Check for pixel pack buffer related API errors
293 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
294 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
295 {
296 // ...the buffer object's data store is currently mapped.
297 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
298 return false;
299 }
300
301 // .. the data would be packed to the buffer object such that the memory writes required
302 // would exceed the data store size.
303 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
304 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
305 const gl::Extents size(width, height, 1);
306 const auto &pack = context->getGLState().getPackState();
307
308 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
309 if (endByteOrErr.isError())
310 {
311 context->handleError(endByteOrErr.getError());
312 return false;
313 }
314
315 size_t endByte = endByteOrErr.getResult();
316 if (bufSize >= 0)
317 {
318
319 if (static_cast<size_t>(bufSize) < endByte)
320 {
321 context->handleError(
322 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
323 return false;
324 }
325 }
326
327 if (pixelPackBuffer != nullptr)
328 {
329 CheckedNumeric<size_t> checkedEndByte(endByte);
330 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
331 checkedEndByte += checkedOffset;
332
333 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
334 {
335 // Overflow past the end of the buffer
336 context->handleError(
337 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
338 return false;
339 }
340 }
341
342 if (length != nullptr)
343 {
344 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
345 {
346 context->handleError(
347 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
348 return false;
349 }
350
351 *length = static_cast<GLsizei>(endByte);
352 }
353
354 return true;
355}
356
Geoff Lang740d9022016-10-07 11:20:52 -0400357bool ValidateGetRenderbufferParameterivBase(Context *context,
358 GLenum target,
359 GLenum pname,
360 GLsizei *length)
361{
362 if (length)
363 {
364 *length = 0;
365 }
366
367 if (target != GL_RENDERBUFFER)
368 {
369 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
370 return false;
371 }
372
373 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
374 if (renderbuffer == nullptr)
375 {
376 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
377 return false;
378 }
379
380 switch (pname)
381 {
382 case GL_RENDERBUFFER_WIDTH:
383 case GL_RENDERBUFFER_HEIGHT:
384 case GL_RENDERBUFFER_INTERNAL_FORMAT:
385 case GL_RENDERBUFFER_RED_SIZE:
386 case GL_RENDERBUFFER_GREEN_SIZE:
387 case GL_RENDERBUFFER_BLUE_SIZE:
388 case GL_RENDERBUFFER_ALPHA_SIZE:
389 case GL_RENDERBUFFER_DEPTH_SIZE:
390 case GL_RENDERBUFFER_STENCIL_SIZE:
391 break;
392
393 case GL_RENDERBUFFER_SAMPLES_ANGLE:
394 if (!context->getExtensions().framebufferMultisample)
395 {
396 context->handleError(
397 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
398 return false;
399 }
400 break;
401
402 default:
403 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
404 return false;
405 }
406
407 if (length)
408 {
409 *length = 1;
410 }
411 return true;
412}
413
Geoff Langd7d0ed32016-10-07 11:33:51 -0400414bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
415{
416 if (length)
417 {
418 *length = 0;
419 }
420
421 if (GetValidShader(context, shader) == nullptr)
422 {
423 return false;
424 }
425
426 switch (pname)
427 {
428 case GL_SHADER_TYPE:
429 case GL_DELETE_STATUS:
430 case GL_COMPILE_STATUS:
431 case GL_INFO_LOG_LENGTH:
432 case GL_SHADER_SOURCE_LENGTH:
433 break;
434
435 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
436 if (!context->getExtensions().translatedShaderSource)
437 {
438 context->handleError(
439 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
440 return false;
441 }
442 break;
443
444 default:
445 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
446 return false;
447 }
448
449 if (length)
450 {
451 *length = 1;
452 }
453 return true;
454}
455
Geoff Langc1984ed2016-10-07 12:41:00 -0400456bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
457{
458 if (length)
459 {
460 *length = 0;
461 }
462
463 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
464 {
465 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
466 return false;
467 }
468
469 if (context->getTargetTexture(target) == nullptr)
470 {
471 // Should only be possible for external textures
472 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
473 return false;
474 }
475
476 switch (pname)
477 {
478 case GL_TEXTURE_MAG_FILTER:
479 case GL_TEXTURE_MIN_FILTER:
480 case GL_TEXTURE_WRAP_S:
481 case GL_TEXTURE_WRAP_T:
482 break;
483
484 case GL_TEXTURE_USAGE_ANGLE:
485 if (!context->getExtensions().textureUsage)
486 {
487 context->handleError(
488 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
489 return false;
490 }
491 break;
492
493 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
494 if (!context->getExtensions().textureFilterAnisotropic)
495 {
496 context->handleError(
497 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
498 return false;
499 }
500 break;
501
502 case GL_TEXTURE_IMMUTABLE_FORMAT:
503 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
504 {
505 context->handleError(
506 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
507 return false;
508 }
509 break;
510
511 case GL_TEXTURE_WRAP_R:
512 case GL_TEXTURE_IMMUTABLE_LEVELS:
513 case GL_TEXTURE_SWIZZLE_R:
514 case GL_TEXTURE_SWIZZLE_G:
515 case GL_TEXTURE_SWIZZLE_B:
516 case GL_TEXTURE_SWIZZLE_A:
517 case GL_TEXTURE_BASE_LEVEL:
518 case GL_TEXTURE_MAX_LEVEL:
519 case GL_TEXTURE_MIN_LOD:
520 case GL_TEXTURE_MAX_LOD:
521 case GL_TEXTURE_COMPARE_MODE:
522 case GL_TEXTURE_COMPARE_FUNC:
523 if (context->getClientMajorVersion() < 3)
524 {
525 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
526 return false;
527 }
528 break;
529
Geoff Lang81c6b572016-10-19 14:07:52 -0700530 case GL_TEXTURE_SRGB_DECODE_EXT:
531 if (!context->getExtensions().textureSRGBDecode)
532 {
533 context->handleError(
534 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
535 return false;
536 }
537 break;
538
Geoff Langc1984ed2016-10-07 12:41:00 -0400539 default:
540 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
541 return false;
542 }
543
544 if (length)
545 {
546 *length = 1;
547 }
548 return true;
549}
550
551template <typename ParamType>
552bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
553{
554 switch (ConvertToGLenum(params[0]))
555 {
556 case GL_CLAMP_TO_EDGE:
557 break;
558
559 case GL_REPEAT:
560 case GL_MIRRORED_REPEAT:
561 if (isExternalTextureTarget)
562 {
563 // OES_EGL_image_external specifies this error.
564 context->handleError(Error(
565 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
566 return false;
567 }
568 break;
569
570 default:
571 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
572 return false;
573 }
574
575 return true;
576}
577
578template <typename ParamType>
579bool ValidateTextureMinFilterValue(Context *context,
580 ParamType *params,
581 bool isExternalTextureTarget)
582{
583 switch (ConvertToGLenum(params[0]))
584 {
585 case GL_NEAREST:
586 case GL_LINEAR:
587 break;
588
589 case GL_NEAREST_MIPMAP_NEAREST:
590 case GL_LINEAR_MIPMAP_NEAREST:
591 case GL_NEAREST_MIPMAP_LINEAR:
592 case GL_LINEAR_MIPMAP_LINEAR:
593 if (isExternalTextureTarget)
594 {
595 // OES_EGL_image_external specifies this error.
596 context->handleError(
597 Error(GL_INVALID_ENUM,
598 "external textures only support NEAREST and LINEAR filtering"));
599 return false;
600 }
601 break;
602
603 default:
604 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
605 return false;
606 }
607
608 return true;
609}
610
611template <typename ParamType>
612bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
613{
614 switch (ConvertToGLenum(params[0]))
615 {
616 case GL_NEAREST:
617 case GL_LINEAR:
618 break;
619
620 default:
621 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
622 return false;
623 }
624
625 return true;
626}
627
628template <typename ParamType>
629bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
630{
631 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
632 switch (ConvertToGLenum(params[0]))
633 {
634 case GL_NONE:
635 case GL_COMPARE_REF_TO_TEXTURE:
636 break;
637
638 default:
639 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
640 return false;
641 }
642
643 return true;
644}
645
646template <typename ParamType>
647bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
648{
649 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
650 switch (ConvertToGLenum(params[0]))
651 {
652 case GL_LEQUAL:
653 case GL_GEQUAL:
654 case GL_LESS:
655 case GL_GREATER:
656 case GL_EQUAL:
657 case GL_NOTEQUAL:
658 case GL_ALWAYS:
659 case GL_NEVER:
660 break;
661
662 default:
663 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
664 return false;
665 }
666
667 return true;
668}
669
670template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700671bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
672{
673 if (!context->getExtensions().textureSRGBDecode)
674 {
675 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
676 return false;
677 }
678
679 switch (ConvertToGLenum(params[0]))
680 {
681 case GL_DECODE_EXT:
682 case GL_SKIP_DECODE_EXT:
683 break;
684
685 default:
686 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
687 return false;
688 }
689
690 return true;
691}
692
693template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400694bool ValidateTexParameterBase(Context *context,
695 GLenum target,
696 GLenum pname,
697 GLsizei bufSize,
698 ParamType *params)
699{
700 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
701 {
702 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
703 return false;
704 }
705
706 if (context->getTargetTexture(target) == nullptr)
707 {
708 // Should only be possible for external textures
709 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
710 return false;
711 }
712
713 const GLsizei minBufSize = 1;
714 if (bufSize >= 0 && bufSize < minBufSize)
715 {
716 context->handleError(
717 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
718 return false;
719 }
720
721 switch (pname)
722 {
723 case GL_TEXTURE_WRAP_R:
724 case GL_TEXTURE_SWIZZLE_R:
725 case GL_TEXTURE_SWIZZLE_G:
726 case GL_TEXTURE_SWIZZLE_B:
727 case GL_TEXTURE_SWIZZLE_A:
728 case GL_TEXTURE_BASE_LEVEL:
729 case GL_TEXTURE_MAX_LEVEL:
730 case GL_TEXTURE_COMPARE_MODE:
731 case GL_TEXTURE_COMPARE_FUNC:
732 case GL_TEXTURE_MIN_LOD:
733 case GL_TEXTURE_MAX_LOD:
734 if (context->getClientMajorVersion() < 3)
735 {
736 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
737 return false;
738 }
739 if (target == GL_TEXTURE_EXTERNAL_OES &&
740 !context->getExtensions().eglImageExternalEssl3)
741 {
742 context->handleError(Error(GL_INVALID_ENUM,
743 "ES3 texture parameters are not available without "
744 "GL_OES_EGL_image_external_essl3."));
745 return false;
746 }
747 break;
748
749 default:
750 break;
751 }
752
753 switch (pname)
754 {
755 case GL_TEXTURE_WRAP_S:
756 case GL_TEXTURE_WRAP_T:
757 case GL_TEXTURE_WRAP_R:
758 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
759 {
760 return false;
761 }
762 break;
763
764 case GL_TEXTURE_MIN_FILTER:
765 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
766 {
767 return false;
768 }
769 break;
770
771 case GL_TEXTURE_MAG_FILTER:
772 if (!ValidateTextureMagFilterValue(context, params))
773 {
774 return false;
775 }
776 break;
777
778 case GL_TEXTURE_USAGE_ANGLE:
779 switch (ConvertToGLenum(params[0]))
780 {
781 case GL_NONE:
782 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
783 break;
784
785 default:
786 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
787 return false;
788 }
789 break;
790
791 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
792 if (!context->getExtensions().textureFilterAnisotropic)
793 {
794 context->handleError(
795 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
796 return false;
797 }
798
799 // we assume the parameter passed to this validation method is truncated, not rounded
800 if (params[0] < 1)
801 {
802 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
803 return false;
804 }
805 break;
806
807 case GL_TEXTURE_MIN_LOD:
808 case GL_TEXTURE_MAX_LOD:
809 // any value is permissible
810 break;
811
812 case GL_TEXTURE_COMPARE_MODE:
813 if (!ValidateTextureCompareModeValue(context, params))
814 {
815 return false;
816 }
817 break;
818
819 case GL_TEXTURE_COMPARE_FUNC:
820 if (!ValidateTextureCompareFuncValue(context, params))
821 {
822 return false;
823 }
824 break;
825
826 case GL_TEXTURE_SWIZZLE_R:
827 case GL_TEXTURE_SWIZZLE_G:
828 case GL_TEXTURE_SWIZZLE_B:
829 case GL_TEXTURE_SWIZZLE_A:
830 switch (ConvertToGLenum(params[0]))
831 {
832 case GL_RED:
833 case GL_GREEN:
834 case GL_BLUE:
835 case GL_ALPHA:
836 case GL_ZERO:
837 case GL_ONE:
838 break;
839
840 default:
841 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
842 return false;
843 }
844 break;
845
846 case GL_TEXTURE_BASE_LEVEL:
847 if (params[0] < 0)
848 {
849 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
850 return false;
851 }
852 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
853 {
854 context->handleError(
855 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
856 return false;
857 }
858 break;
859
860 case GL_TEXTURE_MAX_LEVEL:
861 if (params[0] < 0)
862 {
863 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
864 return false;
865 }
866 break;
867
Geoff Lang3b573612016-10-31 14:08:10 -0400868 case GL_DEPTH_STENCIL_TEXTURE_MODE:
869 if (context->getClientVersion() < Version(3, 1))
870 {
871 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
872 return false;
873 }
Geoff Lang9f090372016-12-02 10:20:43 -0500874 switch (ConvertToGLenum(params[0]))
875 {
876 case GL_DEPTH_COMPONENT:
877 case GL_STENCIL_INDEX:
878 break;
879
880 default:
881 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
882 return false;
883 }
Geoff Lang3b573612016-10-31 14:08:10 -0400884 break;
885
Geoff Lang81c6b572016-10-19 14:07:52 -0700886 case GL_TEXTURE_SRGB_DECODE_EXT:
887 if (!ValidateTextureSRGBDecodeValue(context, params))
888 {
889 return false;
890 }
891 break;
892
Geoff Langc1984ed2016-10-07 12:41:00 -0400893 default:
894 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
895 return false;
896 }
897
898 return true;
899}
900
901template <typename ParamType>
902bool ValidateSamplerParameterBase(Context *context,
903 GLuint sampler,
904 GLenum pname,
905 GLsizei bufSize,
906 ParamType *params)
907{
908 if (context->getClientMajorVersion() < 3)
909 {
910 context->handleError(
911 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
912 return false;
913 }
914
915 if (!context->isSampler(sampler))
916 {
917 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
918 return false;
919 }
920
921 const GLsizei minBufSize = 1;
922 if (bufSize >= 0 && bufSize < minBufSize)
923 {
924 context->handleError(
925 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
926 return false;
927 }
928
929 switch (pname)
930 {
931 case GL_TEXTURE_WRAP_S:
932 case GL_TEXTURE_WRAP_T:
933 case GL_TEXTURE_WRAP_R:
934 if (!ValidateTextureWrapModeValue(context, params, false))
935 {
936 return false;
937 }
938 break;
939
940 case GL_TEXTURE_MIN_FILTER:
941 if (!ValidateTextureMinFilterValue(context, params, false))
942 {
943 return false;
944 }
945 break;
946
947 case GL_TEXTURE_MAG_FILTER:
948 if (!ValidateTextureMagFilterValue(context, params))
949 {
950 return false;
951 }
952 break;
953
954 case GL_TEXTURE_MIN_LOD:
955 case GL_TEXTURE_MAX_LOD:
956 // any value is permissible
957 break;
958
959 case GL_TEXTURE_COMPARE_MODE:
960 if (!ValidateTextureCompareModeValue(context, params))
961 {
962 return false;
963 }
964 break;
965
966 case GL_TEXTURE_COMPARE_FUNC:
967 if (!ValidateTextureCompareFuncValue(context, params))
968 {
969 return false;
970 }
971 break;
972
Geoff Lang81c6b572016-10-19 14:07:52 -0700973 case GL_TEXTURE_SRGB_DECODE_EXT:
974 if (!ValidateTextureSRGBDecodeValue(context, params))
975 {
976 return false;
977 }
978 break;
979
Geoff Langc1984ed2016-10-07 12:41:00 -0400980 default:
981 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
982 return false;
983 }
984
985 return true;
986}
987
988bool ValidateGetSamplerParameterBase(Context *context,
989 GLuint sampler,
990 GLenum pname,
991 GLsizei *length)
992{
993 if (length)
994 {
995 *length = 0;
996 }
997
998 if (context->getClientMajorVersion() < 3)
999 {
1000 context->handleError(
1001 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1002 return false;
1003 }
1004
1005 if (!context->isSampler(sampler))
1006 {
1007 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
1008 return false;
1009 }
1010
1011 switch (pname)
1012 {
1013 case GL_TEXTURE_WRAP_S:
1014 case GL_TEXTURE_WRAP_T:
1015 case GL_TEXTURE_WRAP_R:
1016 case GL_TEXTURE_MIN_FILTER:
1017 case GL_TEXTURE_MAG_FILTER:
1018 case GL_TEXTURE_MIN_LOD:
1019 case GL_TEXTURE_MAX_LOD:
1020 case GL_TEXTURE_COMPARE_MODE:
1021 case GL_TEXTURE_COMPARE_FUNC:
1022 break;
1023
Geoff Lang81c6b572016-10-19 14:07:52 -07001024 case GL_TEXTURE_SRGB_DECODE_EXT:
1025 if (!context->getExtensions().textureSRGBDecode)
1026 {
1027 context->handleError(
1028 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
1029 return false;
1030 }
1031 break;
1032
Geoff Langc1984ed2016-10-07 12:41:00 -04001033 default:
1034 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1035 return false;
1036 }
1037
1038 if (length)
1039 {
1040 *length = 1;
1041 }
1042 return true;
1043}
1044
Geoff Lang0b031062016-10-13 14:30:04 -04001045bool ValidateGetVertexAttribBase(Context *context,
1046 GLuint index,
1047 GLenum pname,
1048 GLsizei *length,
1049 bool pointer,
1050 bool pureIntegerEntryPoint)
1051{
1052 if (length)
1053 {
1054 *length = 0;
1055 }
1056
1057 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1058 {
1059 context->handleError(
1060 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1061 return false;
1062 }
1063
1064 if (index >= context->getCaps().maxVertexAttributes)
1065 {
1066 context->handleError(Error(
1067 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1068 return false;
1069 }
1070
1071 if (pointer)
1072 {
1073 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1074 {
1075 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1076 return false;
1077 }
1078 }
1079 else
1080 {
1081 switch (pname)
1082 {
1083 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1084 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1085 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1086 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1087 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1088 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1089 case GL_CURRENT_VERTEX_ATTRIB:
1090 break;
1091
1092 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1093 static_assert(
1094 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1095 "ANGLE extension enums not equal to GL enums.");
1096 if (context->getClientMajorVersion() < 3 &&
1097 !context->getExtensions().instancedArrays)
1098 {
1099 context->handleError(Error(GL_INVALID_ENUM,
1100 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1101 "3.0 or GL_ANGLE_instanced_arrays."));
1102 return false;
1103 }
1104 break;
1105
1106 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1107 if (context->getClientMajorVersion() < 3)
1108 {
1109 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1110 return false;
1111 }
1112 break;
1113
1114 default:
1115 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1116 return false;
1117 }
1118 }
1119
1120 if (length)
1121 {
1122 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1123 {
1124 *length = 4;
1125 }
1126 else
1127 {
1128 *length = 1;
1129 }
1130 }
1131
1132 return true;
1133}
1134
Geoff Lang6899b872016-10-14 11:30:13 -04001135bool ValidateGetActiveUniformBlockivBase(Context *context,
1136 GLuint program,
1137 GLuint uniformBlockIndex,
1138 GLenum pname,
1139 GLsizei *length)
1140{
1141 if (length)
1142 {
1143 *length = 0;
1144 }
1145
1146 if (context->getClientMajorVersion() < 3)
1147 {
1148 context->handleError(
1149 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1150 return false;
1151 }
1152
1153 Program *programObject = GetValidProgram(context, program);
1154 if (!programObject)
1155 {
1156 return false;
1157 }
1158
1159 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1160 {
1161 context->handleError(
1162 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1163 return false;
1164 }
1165
1166 switch (pname)
1167 {
1168 case GL_UNIFORM_BLOCK_BINDING:
1169 case GL_UNIFORM_BLOCK_DATA_SIZE:
1170 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1171 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1172 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1173 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1174 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1175 break;
1176
1177 default:
1178 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1179 return false;
1180 }
1181
1182 if (length)
1183 {
1184 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1185 {
1186 const UniformBlock &uniformBlock =
1187 programObject->getUniformBlockByIndex(uniformBlockIndex);
1188 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1189 }
1190 else
1191 {
1192 *length = 1;
1193 }
1194 }
1195
1196 return true;
1197}
1198
Geoff Langebebe1c2016-10-14 12:01:31 -04001199bool ValidateGetBufferParameterBase(ValidationContext *context,
1200 GLenum target,
1201 GLenum pname,
1202 bool pointerVersion,
1203 GLsizei *numParams)
1204{
1205 if (numParams)
1206 {
1207 *numParams = 0;
1208 }
1209
1210 if (!ValidBufferTarget(context, target))
1211 {
1212 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1213 return false;
1214 }
1215
1216 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1217 if (!buffer)
1218 {
1219 // A null buffer means that "0" is bound to the requested buffer target
1220 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1221 return false;
1222 }
1223
1224 const Extensions &extensions = context->getExtensions();
1225
1226 switch (pname)
1227 {
1228 case GL_BUFFER_USAGE:
1229 case GL_BUFFER_SIZE:
1230 break;
1231
1232 case GL_BUFFER_ACCESS_OES:
1233 if (!extensions.mapBuffer)
1234 {
1235 context->handleError(
Jamie Madillcc6ac252017-01-25 12:57:21 -08001236 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001237 return false;
1238 }
1239 break;
1240
1241 case GL_BUFFER_MAPPED:
1242 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1243 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1244 !extensions.mapBufferRange)
1245 {
1246 context->handleError(Error(
1247 GL_INVALID_ENUM,
Jamie Madillcc6ac252017-01-25 12:57:21 -08001248 "pname requires OpenGL ES 3.0, GL_OES_mapbuffer or GL_EXT_map_buffer_range."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001249 return false;
1250 }
1251 break;
1252
1253 case GL_BUFFER_MAP_POINTER:
1254 if (!pointerVersion)
1255 {
1256 context->handleError(
1257 Error(GL_INVALID_ENUM,
1258 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1259 return false;
1260 }
1261 break;
1262
1263 case GL_BUFFER_ACCESS_FLAGS:
1264 case GL_BUFFER_MAP_OFFSET:
1265 case GL_BUFFER_MAP_LENGTH:
1266 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1267 {
1268 context->handleError(Error(
1269 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1270 return false;
1271 }
1272 break;
1273
1274 default:
1275 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1276 return false;
1277 }
1278
1279 // All buffer parameter queries return one value.
1280 if (numParams)
1281 {
1282 *numParams = 1;
1283 }
1284
1285 return true;
1286}
1287
Geoff Lang0a9661f2016-10-20 10:59:20 -07001288bool ValidateGetInternalFormativBase(Context *context,
1289 GLenum target,
1290 GLenum internalformat,
1291 GLenum pname,
1292 GLsizei bufSize,
1293 GLsizei *numParams)
1294{
1295 if (numParams)
1296 {
1297 *numParams = 0;
1298 }
1299
1300 if (context->getClientMajorVersion() < 3)
1301 {
1302 context->handleError(
1303 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1304 return false;
1305 }
1306
1307 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1308 if (!formatCaps.renderable)
1309 {
1310 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1311 return false;
1312 }
1313
1314 switch (target)
1315 {
1316 case GL_RENDERBUFFER:
1317 break;
1318
JiangYizhoubddc46b2016-12-09 09:50:51 +08001319 case GL_TEXTURE_2D_MULTISAMPLE:
1320 if (context->getClientVersion() < ES_3_1)
1321 {
1322 context->handleError(
1323 Error(GL_INVALID_OPERATION, "Texture target requires at least OpenGL ES 3.1."));
1324 return false;
1325 }
1326 break;
1327
Geoff Lang0a9661f2016-10-20 10:59:20 -07001328 default:
1329 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1330 return false;
1331 }
1332
1333 if (bufSize < 0)
1334 {
1335 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1336 return false;
1337 }
1338
1339 GLsizei maxWriteParams = 0;
1340 switch (pname)
1341 {
1342 case GL_NUM_SAMPLE_COUNTS:
1343 maxWriteParams = 1;
1344 break;
1345
1346 case GL_SAMPLES:
1347 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1348 break;
1349
1350 default:
1351 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1352 return false;
1353 }
1354
1355 if (numParams)
1356 {
1357 // glGetInternalFormativ will not overflow bufSize
1358 *numParams = std::min(bufSize, maxWriteParams);
1359 }
1360
1361 return true;
1362}
1363
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001364bool ValidateUniformCommonBase(gl::Context *context,
1365 gl::Program *program,
1366 GLint location,
1367 GLsizei count,
1368 const LinkedUniform **uniformOut)
1369{
1370 // TODO(Jiajia): Add image uniform check in future.
1371 if (count < 0)
1372 {
1373 context->handleError(Error(GL_INVALID_VALUE));
1374 return false;
1375 }
1376
1377 if (!program || !program->isLinked())
1378 {
1379 context->handleError(Error(GL_INVALID_OPERATION));
1380 return false;
1381 }
1382
1383 if (location == -1)
1384 {
1385 // Silently ignore the uniform command
1386 return false;
1387 }
1388
1389 const auto &uniformLocations = program->getUniformLocations();
1390 size_t castedLocation = static_cast<size_t>(location);
1391 if (castedLocation >= uniformLocations.size())
1392 {
1393 context->handleError(Error(GL_INVALID_OPERATION, "Invalid uniform location"));
1394 return false;
1395 }
1396
1397 const auto &uniformLocation = uniformLocations[castedLocation];
1398 if (uniformLocation.ignored)
1399 {
1400 // Silently ignore the uniform command
1401 return false;
1402 }
1403
1404 if (!uniformLocation.used)
1405 {
1406 context->handleError(Error(GL_INVALID_OPERATION));
1407 return false;
1408 }
1409
1410 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
1411
1412 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
1413 if (!uniform.isArray() && count > 1)
1414 {
1415 context->handleError(Error(GL_INVALID_OPERATION));
1416 return false;
1417 }
1418
1419 *uniformOut = &uniform;
1420 return true;
1421}
1422
Frank Henigman999b0fd2017-02-02 21:45:55 -05001423bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -05001424 GLenum uniformType,
1425 GLsizei count,
1426 const GLint *value)
1427{
1428 // Value type is GL_INT, because we only get here from glUniform1i{v}.
1429 // It is compatible with INT or BOOL.
1430 // Do these cheap tests first, for a little extra speed.
1431 if (GL_INT == uniformType || GL_BOOL == uniformType)
1432 {
1433 return true;
1434 }
1435
1436 if (IsSamplerType(uniformType))
1437 {
Frank Henigman999b0fd2017-02-02 21:45:55 -05001438 // Check that the values are in range.
1439 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
1440 for (GLsizei i = 0; i < count; ++i)
1441 {
1442 if (value[i] < 0 || value[i] >= max)
1443 {
1444 context->handleError(Error(GL_INVALID_VALUE, "sampler uniform value out of range"));
1445 return false;
1446 }
1447 }
Frank Henigmana98a6472017-02-02 21:38:32 -05001448 return true;
1449 }
1450
1451 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1452 return false;
1453}
1454
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001455bool ValidateUniformValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1456{
1457 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -05001458 // Do the cheaper test first, for a little extra speed.
1459 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001460 {
1461 return true;
1462 }
1463
1464 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1465 return false;
1466}
1467
1468bool ValidateUniformMatrixValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1469{
1470 // Check that the value type is compatible with uniform type.
1471 if (valueType == uniformType)
1472 {
1473 return true;
1474 }
1475
1476 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1477 return false;
1478}
1479
Geoff Langf41a7152016-09-19 15:11:17 -04001480} // anonymous namespace
1481
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001482bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001483{
Jamie Madilld7460c72014-01-21 16:38:14 -05001484 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001485 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001486 case GL_TEXTURE_2D:
1487 case GL_TEXTURE_CUBE_MAP:
1488 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001489
He Yunchaoced53ae2016-11-29 15:00:51 +08001490 case GL_TEXTURE_3D:
1491 case GL_TEXTURE_2D_ARRAY:
1492 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001493
He Yunchaoced53ae2016-11-29 15:00:51 +08001494 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001495 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001496
He Yunchaoced53ae2016-11-29 15:00:51 +08001497 default:
1498 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001499 }
Jamie Madill35d15012013-10-07 10:46:37 -04001500}
1501
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001502bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1503{
1504 switch (target)
1505 {
1506 case GL_TEXTURE_2D:
1507 case GL_TEXTURE_CUBE_MAP:
1508 return true;
1509
1510 default:
1511 return false;
1512 }
1513}
1514
1515bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1516{
1517 switch (target)
1518 {
1519 case GL_TEXTURE_3D:
1520 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001521 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001522
1523 default:
1524 return false;
1525 }
1526}
1527
Ian Ewellbda75592016-04-18 17:25:54 -04001528// Most texture GL calls are not compatible with external textures, so we have a separate validation
1529// function for use in the GL calls that do
1530bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1531{
1532 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1533 (context->getExtensions().eglImageExternal ||
1534 context->getExtensions().eglStreamConsumerExternal);
1535}
1536
Shannon Woods4dfed832014-03-17 20:03:39 -04001537// This function differs from ValidTextureTarget in that the target must be
1538// usable as the destination of a 2D operation-- so a cube face is valid, but
1539// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001540// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001541bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001542{
1543 switch (target)
1544 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001545 case GL_TEXTURE_2D:
1546 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1547 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1548 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1549 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1550 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1551 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1552 return true;
1553 default:
1554 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001555 }
1556}
1557
1558bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1559{
1560 switch (target)
1561 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001562 case GL_TEXTURE_3D:
1563 case GL_TEXTURE_2D_ARRAY:
1564 return true;
1565 default:
1566 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001567 }
1568}
1569
He Yunchao11b038b2016-11-22 21:24:04 +08001570bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1571{
1572 switch (target)
1573 {
1574 case GL_TEXTURE_2D:
1575 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1576 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1577 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1578 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1579 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1580 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1581 case GL_TEXTURE_3D:
1582 case GL_TEXTURE_2D_ARRAY:
1583 case GL_TEXTURE_2D_MULTISAMPLE:
1584 return true;
1585 default:
1586 return false;
1587 }
1588}
1589
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001590bool ValidFramebufferTarget(GLenum target)
1591{
He Yunchaoced53ae2016-11-29 15:00:51 +08001592 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1593 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001594 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001595
1596 switch (target)
1597 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001598 case GL_FRAMEBUFFER:
1599 return true;
1600 case GL_READ_FRAMEBUFFER:
1601 return true;
1602 case GL_DRAW_FRAMEBUFFER:
1603 return true;
1604 default:
1605 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001606 }
1607}
1608
Jamie Madill29639852016-09-02 15:00:09 -04001609bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001610{
1611 switch (target)
1612 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001613 case GL_ARRAY_BUFFER:
1614 case GL_ELEMENT_ARRAY_BUFFER:
1615 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001616
He Yunchaoced53ae2016-11-29 15:00:51 +08001617 case GL_PIXEL_PACK_BUFFER:
1618 case GL_PIXEL_UNPACK_BUFFER:
1619 return (context->getExtensions().pixelBufferObject ||
1620 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001621
He Yunchaoced53ae2016-11-29 15:00:51 +08001622 case GL_COPY_READ_BUFFER:
1623 case GL_COPY_WRITE_BUFFER:
1624 case GL_TRANSFORM_FEEDBACK_BUFFER:
1625 case GL_UNIFORM_BUFFER:
1626 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001627
He Yunchaoced53ae2016-11-29 15:00:51 +08001628 case GL_ATOMIC_COUNTER_BUFFER:
1629 case GL_SHADER_STORAGE_BUFFER:
1630 case GL_DRAW_INDIRECT_BUFFER:
1631 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001632 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001633
He Yunchaoced53ae2016-11-29 15:00:51 +08001634 default:
1635 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001636 }
1637}
1638
Jamie Madillc29968b2016-01-20 11:17:23 -05001639bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001640{
Jamie Madillc29968b2016-01-20 11:17:23 -05001641 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001642 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001643 switch (target)
1644 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001645 case GL_TEXTURE_2D:
1646 maxDimension = caps.max2DTextureSize;
1647 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001648 case GL_TEXTURE_CUBE_MAP:
1649 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1650 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1651 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1652 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1653 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1654 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1655 maxDimension = caps.maxCubeMapTextureSize;
1656 break;
1657 case GL_TEXTURE_3D:
1658 maxDimension = caps.max3DTextureSize;
1659 break;
1660 case GL_TEXTURE_2D_ARRAY:
1661 maxDimension = caps.max2DTextureSize;
1662 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001663 case GL_TEXTURE_2D_MULTISAMPLE:
1664 maxDimension = caps.max2DTextureSize;
1665 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001666 default:
1667 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001668 }
1669
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001670 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001671}
1672
Geoff Langcc507aa2016-12-12 10:09:52 -05001673bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001674 GLenum target,
1675 GLint level,
1676 GLsizei width,
1677 GLsizei height,
1678 GLsizei depth,
1679 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001680{
1681 if (level < 0 || width < 0 || height < 0 || depth < 0)
1682 {
1683 return false;
1684 }
1685
Austin Kinross08528e12015-10-07 16:24:40 -07001686 // TexSubImage parameters can be NPOT without textureNPOT extension,
1687 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001688 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001689 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001690 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001691 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001692 {
1693 return false;
1694 }
1695
1696 if (!ValidMipLevel(context, target, level))
1697 {
1698 return false;
1699 }
1700
1701 return true;
1702}
1703
Geoff Lang0d8b7242015-09-09 14:56:53 -04001704bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1705{
1706 // List of compressed format that require that the texture size is smaller than or a multiple of
1707 // the compressed block size.
1708 switch (internalFormat)
1709 {
1710 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1711 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1712 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1713 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001714 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001715 return true;
1716
1717 default:
1718 return false;
1719 }
1720}
1721
Jamie Madillc29968b2016-01-20 11:17:23 -05001722bool ValidCompressedImageSize(const ValidationContext *context,
1723 GLenum internalFormat,
Geoff Lang44ff5a72017-02-03 15:15:43 -05001724 GLint xoffset,
1725 GLint yoffset,
Jamie Madillc29968b2016-01-20 11:17:23 -05001726 GLsizei width,
1727 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001728{
Geoff Lang5d601382014-07-22 15:14:06 -04001729 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1730 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001731 {
1732 return false;
1733 }
1734
Geoff Lang44ff5a72017-02-03 15:15:43 -05001735 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001736 {
1737 return false;
1738 }
1739
Geoff Lang0d8b7242015-09-09 14:56:53 -04001740 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1741 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001742 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
1743 yoffset % formatInfo.compressedBlockHeight != 0 ||
1744 (static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
Geoff Lang0d8b7242015-09-09 14:56:53 -04001745 width % formatInfo.compressedBlockWidth != 0) ||
1746 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1747 height % formatInfo.compressedBlockHeight != 0))
1748 {
1749 return false;
1750 }
1751 }
1752
Geoff Langd4f180b2013-09-24 13:57:44 -04001753 return true;
1754}
1755
Geoff Langff5b2d52016-09-07 11:32:23 -04001756bool ValidImageDataSize(ValidationContext *context,
1757 GLenum textureTarget,
1758 GLsizei width,
1759 GLsizei height,
1760 GLsizei depth,
1761 GLenum internalFormat,
1762 GLenum type,
1763 const GLvoid *pixels,
1764 GLsizei imageSize)
1765{
1766 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1767 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1768 {
1769 // Checks are not required
1770 return true;
1771 }
1772
1773 // ...the data would be unpacked from the buffer object such that the memory reads required
1774 // would exceed the data store size.
1775 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1776 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1777 const gl::Extents size(width, height, depth);
1778 const auto &unpack = context->getGLState().getUnpackState();
1779
1780 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1781 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1782 if (endByteOrErr.isError())
1783 {
1784 context->handleError(endByteOrErr.getError());
1785 return false;
1786 }
1787
1788 GLuint endByte = endByteOrErr.getResult();
1789
1790 if (pixelUnpackBuffer)
1791 {
1792 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1793 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1794 checkedEndByte += checkedOffset;
1795
1796 if (!checkedEndByte.IsValid() ||
1797 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1798 {
1799 // Overflow past the end of the buffer
1800 context->handleError(Error(GL_INVALID_OPERATION));
1801 return false;
1802 }
1803 }
1804 else
1805 {
1806 ASSERT(imageSize >= 0);
1807 if (pixels == nullptr && imageSize != 0)
1808 {
1809 context->handleError(
1810 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001811 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001812 }
1813
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001814 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001815 {
1816 context->handleError(
1817 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1818 return false;
1819 }
1820 }
1821
1822 return true;
1823}
1824
Geoff Lang37dde692014-01-31 16:34:54 -05001825bool ValidQueryType(const Context *context, GLenum queryType)
1826{
He Yunchaoced53ae2016-11-29 15:00:51 +08001827 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1828 "GL extension enums not equal.");
1829 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1830 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001831
1832 switch (queryType)
1833 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001834 case GL_ANY_SAMPLES_PASSED:
1835 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1836 return true;
1837 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1838 return (context->getClientMajorVersion() >= 3);
1839 case GL_TIME_ELAPSED_EXT:
1840 return context->getExtensions().disjointTimerQuery;
1841 case GL_COMMANDS_COMPLETED_CHROMIUM:
1842 return context->getExtensions().syncQuery;
1843 default:
1844 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001845 }
1846}
1847
Jamie Madillef300b12016-10-07 15:12:09 -04001848Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001849{
He Yunchaoced53ae2016-11-29 15:00:51 +08001850 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1851 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1852 // or program object and INVALID_OPERATION if the provided name identifies an object
1853 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001854
Dian Xiang769769a2015-09-09 15:20:08 -07001855 Program *validProgram = context->getProgram(id);
1856
1857 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001858 {
Dian Xiang769769a2015-09-09 15:20:08 -07001859 if (context->getShader(id))
1860 {
Jamie Madill437fa652016-05-03 15:13:24 -04001861 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001862 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1863 }
1864 else
1865 {
Jamie Madill437fa652016-05-03 15:13:24 -04001866 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001867 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001868 }
Dian Xiang769769a2015-09-09 15:20:08 -07001869
1870 return validProgram;
1871}
1872
Jamie Madillef300b12016-10-07 15:12:09 -04001873Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001874{
1875 // See ValidProgram for spec details.
1876
1877 Shader *validShader = context->getShader(id);
1878
1879 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001880 {
Dian Xiang769769a2015-09-09 15:20:08 -07001881 if (context->getProgram(id))
1882 {
Jamie Madill437fa652016-05-03 15:13:24 -04001883 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001884 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1885 }
1886 else
1887 {
Jamie Madill437fa652016-05-03 15:13:24 -04001888 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001889 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001890 }
Dian Xiang769769a2015-09-09 15:20:08 -07001891
1892 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001893}
1894
Geoff Langb1196682014-07-23 13:47:29 -04001895bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001896{
1897 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1898 {
1899 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1900
Geoff Langaae65a42014-05-26 12:43:44 -04001901 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001902 {
Jamie Madill437fa652016-05-03 15:13:24 -04001903 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001904 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001905 }
1906 }
1907 else
1908 {
1909 switch (attachment)
1910 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001911 case GL_DEPTH_ATTACHMENT:
1912 case GL_STENCIL_ATTACHMENT:
1913 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001914
He Yunchaoced53ae2016-11-29 15:00:51 +08001915 case GL_DEPTH_STENCIL_ATTACHMENT:
1916 if (!context->getExtensions().webglCompatibility &&
1917 context->getClientMajorVersion() < 3)
1918 {
1919 context->handleError(Error(GL_INVALID_ENUM));
1920 return false;
1921 }
1922 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001923
He Yunchaoced53ae2016-11-29 15:00:51 +08001924 default:
1925 context->handleError(Error(GL_INVALID_ENUM));
1926 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001927 }
1928 }
1929
1930 return true;
1931}
1932
Jamie Madille8fb6402017-02-14 17:56:40 -05001933bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001934 GLenum target,
1935 GLsizei samples,
1936 GLenum internalformat,
1937 GLsizei width,
1938 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001939{
1940 switch (target)
1941 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001942 case GL_RENDERBUFFER:
1943 break;
1944 default:
1945 context->handleError(Error(GL_INVALID_ENUM));
1946 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001947 }
1948
1949 if (width < 0 || height < 0 || samples < 0)
1950 {
Jamie Madill437fa652016-05-03 15:13:24 -04001951 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001952 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001953 }
1954
Geoff Langd87878e2014-09-19 15:42:59 -04001955 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1956 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001957 {
Jamie Madill437fa652016-05-03 15:13:24 -04001958 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001959 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001960 }
1961
1962 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1963 // 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 -08001964 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001965 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001966 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001967 {
Jamie Madill437fa652016-05-03 15:13:24 -04001968 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001969 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001970 }
1971
Geoff Langaae65a42014-05-26 12:43:44 -04001972 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001973 {
Jamie Madill437fa652016-05-03 15:13:24 -04001974 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001975 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001976 }
1977
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001978 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001979 if (handle == 0)
1980 {
Jamie Madill437fa652016-05-03 15:13:24 -04001981 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001982 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001983 }
1984
1985 return true;
1986}
1987
He Yunchaoced53ae2016-11-29 15:00:51 +08001988bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1989 GLenum target,
1990 GLenum attachment,
1991 GLenum renderbuffertarget,
1992 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001993{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001994 if (!ValidFramebufferTarget(target))
1995 {
Jamie Madill437fa652016-05-03 15:13:24 -04001996 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001997 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001998 }
1999
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002000 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002001
Jamie Madill84115c92015-04-23 15:00:07 -04002002 ASSERT(framebuffer);
2003 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002004 {
Jamie Madill437fa652016-05-03 15:13:24 -04002005 context->handleError(
2006 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002007 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002008 }
2009
Jamie Madillb4472272014-07-03 10:38:55 -04002010 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002011 {
Jamie Madillb4472272014-07-03 10:38:55 -04002012 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002013 }
2014
Jamie Madillab9d82c2014-01-21 16:38:14 -05002015 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2016 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2017 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2018 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2019 if (renderbuffer != 0)
2020 {
2021 if (!context->getRenderbuffer(renderbuffer))
2022 {
Jamie Madill437fa652016-05-03 15:13:24 -04002023 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002024 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05002025 }
2026 }
2027
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002028 return true;
2029}
2030
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002031bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002032 GLint srcX0,
2033 GLint srcY0,
2034 GLint srcX1,
2035 GLint srcY1,
2036 GLint dstX0,
2037 GLint dstY0,
2038 GLint dstX1,
2039 GLint dstY1,
2040 GLbitfield mask,
2041 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002042{
2043 switch (filter)
2044 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002045 case GL_NEAREST:
2046 break;
2047 case GL_LINEAR:
2048 break;
2049 default:
2050 context->handleError(Error(GL_INVALID_ENUM));
2051 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002052 }
2053
2054 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
2055 {
Jamie Madill437fa652016-05-03 15:13:24 -04002056 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002057 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002058 }
2059
2060 if (mask == 0)
2061 {
2062 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
2063 // buffers are copied.
2064 return false;
2065 }
2066
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002067 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
2068 // color buffer, leaving only nearest being unfiltered from above
2069 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
2070 {
Jamie Madill437fa652016-05-03 15:13:24 -04002071 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002072 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002073 }
2074
Jamie Madill51f40ec2016-06-15 14:06:00 -04002075 const auto &glState = context->getGLState();
2076 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2077 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05002078
2079 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002080 {
Jamie Madill437fa652016-05-03 15:13:24 -04002081 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002082 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002083 }
2084
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002085 if (readFramebuffer->id() == drawFramebuffer->id())
2086 {
2087 context->handleError(Error(GL_INVALID_OPERATION));
2088 return false;
2089 }
2090
Jamie Madill51f40ec2016-06-15 14:06:00 -04002091 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002092 {
Jamie Madill437fa652016-05-03 15:13:24 -04002093 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002094 return false;
2095 }
2096
Jamie Madill51f40ec2016-06-15 14:06:00 -04002097 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002098 {
Jamie Madill437fa652016-05-03 15:13:24 -04002099 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002100 return false;
2101 }
2102
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002103 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002104 {
Jamie Madill437fa652016-05-03 15:13:24 -04002105 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002106 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002107 }
2108
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002109 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2110
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002111 if (mask & GL_COLOR_BUFFER_BIT)
2112 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002113 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002114 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002115
He Yunchao66a41a22016-12-15 16:45:05 +08002116 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002117 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002118 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002119
Geoff Langa15472a2015-08-11 11:48:03 -04002120 for (size_t drawbufferIdx = 0;
2121 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002122 {
Geoff Langa15472a2015-08-11 11:48:03 -04002123 const FramebufferAttachment *attachment =
2124 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2125 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002126 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002127 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002128
Geoff Langb2f3d052013-08-13 12:49:27 -04002129 // The GL ES 3.0.2 spec (pg 193) states that:
2130 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002131 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2132 // as well
2133 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2134 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002135 // Changes with EXT_color_buffer_float:
2136 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002137 GLenum readComponentType = readFormat.info->componentType;
2138 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002139 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002140 readComponentType == GL_SIGNED_NORMALIZED);
2141 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2142 drawComponentType == GL_SIGNED_NORMALIZED);
2143
2144 if (extensions.colorBufferFloat)
2145 {
2146 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2147 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2148
2149 if (readFixedOrFloat != drawFixedOrFloat)
2150 {
Jamie Madill437fa652016-05-03 15:13:24 -04002151 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002152 "If the read buffer contains fixed-point or "
2153 "floating-point values, the draw buffer "
2154 "must as well."));
2155 return false;
2156 }
2157 }
2158 else if (readFixedPoint != drawFixedPoint)
2159 {
Jamie Madill437fa652016-05-03 15:13:24 -04002160 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002161 "If the read buffer contains fixed-point "
2162 "values, the draw buffer must as well."));
2163 return false;
2164 }
2165
2166 if (readComponentType == GL_UNSIGNED_INT &&
2167 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002168 {
Jamie Madill437fa652016-05-03 15:13:24 -04002169 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002170 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002171 }
2172
Jamie Madill6163c752015-12-07 16:32:59 -05002173 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002174 {
Jamie Madill437fa652016-05-03 15:13:24 -04002175 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002176 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002177 }
2178
Jamie Madilla3944d42016-07-22 22:13:26 -04002179 if (readColorBuffer->getSamples() > 0 &&
2180 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002181 {
Jamie Madill437fa652016-05-03 15:13:24 -04002182 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002183 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002184 }
2185 }
2186 }
2187
Jamie Madilla3944d42016-07-22 22:13:26 -04002188 if ((readFormat.info->componentType == GL_INT ||
2189 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2190 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002191 {
Jamie Madill437fa652016-05-03 15:13:24 -04002192 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002193 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002194 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002195 }
He Yunchao66a41a22016-12-15 16:45:05 +08002196 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2197 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2198 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2199 // situation is an application error that would lead to a crash in ANGLE.
2200 else if (drawFramebuffer->hasEnabledDrawBuffer())
2201 {
2202 context->handleError(Error(
2203 GL_INVALID_OPERATION,
2204 "Attempt to read from a missing color attachment of a complete framebuffer."));
2205 return false;
2206 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002207 }
2208
He Yunchaoced53ae2016-11-29 15:00:51 +08002209 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002210 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2211 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002212 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002213 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002214 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002215 const gl::FramebufferAttachment *readBuffer =
2216 readFramebuffer->getAttachment(attachments[i]);
2217 const gl::FramebufferAttachment *drawBuffer =
2218 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002219
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002220 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002221 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002222 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002223 {
Jamie Madill437fa652016-05-03 15:13:24 -04002224 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002225 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002226 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002227
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002228 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002229 {
Jamie Madill437fa652016-05-03 15:13:24 -04002230 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002231 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002232 }
2233 }
He Yunchao66a41a22016-12-15 16:45:05 +08002234 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2235 else if (drawBuffer)
2236 {
2237 context->handleError(Error(GL_INVALID_OPERATION,
2238 "Attempt to read from a missing depth/stencil "
2239 "attachment of a complete framebuffer."));
2240 return false;
2241 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002242 }
2243 }
2244
2245 return true;
2246}
2247
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002248bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002249 GLint x,
2250 GLint y,
2251 GLsizei width,
2252 GLsizei height,
2253 GLenum format,
2254 GLenum type,
2255 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002256{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002257 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2258}
2259
2260bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2261 GLint x,
2262 GLint y,
2263 GLsizei width,
2264 GLsizei height,
2265 GLenum format,
2266 GLenum type,
2267 GLsizei bufSize,
2268 GLsizei *length,
2269 GLvoid *pixels)
2270{
2271 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002272 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002273 return false;
2274 }
2275
Geoff Lang62fce5b2016-09-30 10:46:35 -04002276 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2277 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002278 {
Geoff Langb1196682014-07-23 13:47:29 -04002279 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002280 }
2281
Geoff Lang62fce5b2016-09-30 10:46:35 -04002282 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002283 {
Geoff Langb1196682014-07-23 13:47:29 -04002284 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002285 }
2286
Jamie Madillc29968b2016-01-20 11:17:23 -05002287 return true;
2288}
2289
2290bool ValidateReadnPixelsEXT(Context *context,
2291 GLint x,
2292 GLint y,
2293 GLsizei width,
2294 GLsizei height,
2295 GLenum format,
2296 GLenum type,
2297 GLsizei bufSize,
2298 GLvoid *pixels)
2299{
2300 if (bufSize < 0)
2301 {
Jamie Madill437fa652016-05-03 15:13:24 -04002302 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002303 return false;
2304 }
2305
Geoff Lang62fce5b2016-09-30 10:46:35 -04002306 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2307 pixels);
2308}
Jamie Madill26e91952014-03-05 15:01:27 -05002309
Geoff Lang62fce5b2016-09-30 10:46:35 -04002310bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2311 GLint x,
2312 GLint y,
2313 GLsizei width,
2314 GLsizei height,
2315 GLenum format,
2316 GLenum type,
2317 GLsizei bufSize,
2318 GLsizei *length,
2319 GLvoid *data)
2320{
2321 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002322 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002323 return false;
2324 }
2325
Geoff Lang62fce5b2016-09-30 10:46:35 -04002326 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002327 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002328 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002329 }
2330
Geoff Lang62fce5b2016-09-30 10:46:35 -04002331 if (!ValidateRobustBufferSize(context, bufSize, *length))
2332 {
2333 return false;
2334 }
2335
2336 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002337}
2338
Olli Etuaho41997e72016-03-10 13:38:39 +02002339bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002340{
2341 if (!context->getExtensions().occlusionQueryBoolean &&
2342 !context->getExtensions().disjointTimerQuery)
2343 {
Jamie Madill437fa652016-05-03 15:13:24 -04002344 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002345 return false;
2346 }
2347
Olli Etuaho41997e72016-03-10 13:38:39 +02002348 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002349}
2350
Olli Etuaho41997e72016-03-10 13:38:39 +02002351bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002352{
2353 if (!context->getExtensions().occlusionQueryBoolean &&
2354 !context->getExtensions().disjointTimerQuery)
2355 {
Jamie Madill437fa652016-05-03 15:13:24 -04002356 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002357 return false;
2358 }
2359
Olli Etuaho41997e72016-03-10 13:38:39 +02002360 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002361}
2362
2363bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002364{
2365 if (!ValidQueryType(context, target))
2366 {
Jamie Madill437fa652016-05-03 15:13:24 -04002367 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002368 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002369 }
2370
2371 if (id == 0)
2372 {
Jamie Madill437fa652016-05-03 15:13:24 -04002373 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002374 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002375 }
2376
2377 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2378 // of zero, if the active query object name for <target> is non-zero (for the
2379 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2380 // the active query for either target is non-zero), if <id> is the name of an
2381 // existing query object whose type does not match <target>, or if <id> is the
2382 // active query object name for any query type, the error INVALID_OPERATION is
2383 // generated.
2384
2385 // Ensure no other queries are active
2386 // NOTE: If other queries than occlusion are supported, we will need to check
2387 // separately that:
2388 // a) The query ID passed is not the current active query for any target/type
2389 // b) There are no active queries for the requested target (and in the case
2390 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2391 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002392
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002393 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002394 {
Jamie Madill437fa652016-05-03 15:13:24 -04002395 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002396 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002397 }
2398
2399 Query *queryObject = context->getQuery(id, true, target);
2400
2401 // check that name was obtained with glGenQueries
2402 if (!queryObject)
2403 {
Jamie Madill437fa652016-05-03 15:13:24 -04002404 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002405 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002406 }
2407
2408 // check for type mismatch
2409 if (queryObject->getType() != target)
2410 {
Jamie Madill437fa652016-05-03 15:13:24 -04002411 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002412 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002413 }
2414
2415 return true;
2416}
2417
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002418bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2419{
2420 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002421 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002422 {
Jamie Madill437fa652016-05-03 15:13:24 -04002423 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002424 return false;
2425 }
2426
2427 return ValidateBeginQueryBase(context, target, id);
2428}
2429
2430bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002431{
2432 if (!ValidQueryType(context, target))
2433 {
Jamie Madill437fa652016-05-03 15:13:24 -04002434 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002435 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002436 }
2437
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002438 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002439
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002440 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002441 {
Jamie Madill437fa652016-05-03 15:13:24 -04002442 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002443 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002444 }
2445
Jamie Madill45c785d2014-05-13 14:09:34 -04002446 return true;
2447}
2448
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002449bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2450{
2451 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002452 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002453 {
Jamie Madill437fa652016-05-03 15:13:24 -04002454 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002455 return false;
2456 }
2457
2458 return ValidateEndQueryBase(context, target);
2459}
2460
2461bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2462{
2463 if (!context->getExtensions().disjointTimerQuery)
2464 {
Jamie Madill437fa652016-05-03 15:13:24 -04002465 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002466 return false;
2467 }
2468
2469 if (target != GL_TIMESTAMP_EXT)
2470 {
Jamie Madill437fa652016-05-03 15:13:24 -04002471 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002472 return false;
2473 }
2474
2475 Query *queryObject = context->getQuery(id, true, target);
2476 if (queryObject == nullptr)
2477 {
Jamie Madill437fa652016-05-03 15:13:24 -04002478 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002479 return false;
2480 }
2481
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002482 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002483 {
Jamie Madill437fa652016-05-03 15:13:24 -04002484 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002485 return false;
2486 }
2487
2488 return true;
2489}
2490
Geoff Lang2186c382016-10-14 10:54:54 -04002491bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002492{
Geoff Lang2186c382016-10-14 10:54:54 -04002493 if (numParams)
2494 {
2495 *numParams = 0;
2496 }
2497
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002498 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2499 {
Jamie Madill437fa652016-05-03 15:13:24 -04002500 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002501 return false;
2502 }
2503
2504 switch (pname)
2505 {
2506 case GL_CURRENT_QUERY_EXT:
2507 if (target == GL_TIMESTAMP_EXT)
2508 {
Jamie Madill437fa652016-05-03 15:13:24 -04002509 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002510 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2511 return false;
2512 }
2513 break;
2514 case GL_QUERY_COUNTER_BITS_EXT:
2515 if (!context->getExtensions().disjointTimerQuery ||
2516 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2517 {
Jamie Madill437fa652016-05-03 15:13:24 -04002518 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002519 return false;
2520 }
2521 break;
2522 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002523 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002524 return false;
2525 }
2526
Geoff Lang2186c382016-10-14 10:54:54 -04002527 if (numParams)
2528 {
2529 // All queries return only one value
2530 *numParams = 1;
2531 }
2532
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002533 return true;
2534}
2535
2536bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2537{
2538 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002539 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002540 {
Jamie Madill437fa652016-05-03 15:13:24 -04002541 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002542 return false;
2543 }
2544
Geoff Lang2186c382016-10-14 10:54:54 -04002545 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002546}
2547
Geoff Lang2186c382016-10-14 10:54:54 -04002548bool ValidateGetQueryivRobustANGLE(Context *context,
2549 GLenum target,
2550 GLenum pname,
2551 GLsizei bufSize,
2552 GLsizei *length,
2553 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002554{
Geoff Lang2186c382016-10-14 10:54:54 -04002555 if (!ValidateRobustEntryPoint(context, bufSize))
2556 {
2557 return false;
2558 }
2559
2560 if (!ValidateGetQueryivBase(context, target, pname, length))
2561 {
2562 return false;
2563 }
2564
2565 if (!ValidateRobustBufferSize(context, bufSize, *length))
2566 {
2567 return false;
2568 }
2569
2570 return true;
2571}
2572
2573bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2574{
2575 if (numParams)
2576 {
2577 *numParams = 0;
2578 }
2579
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002580 Query *queryObject = context->getQuery(id, false, GL_NONE);
2581
2582 if (!queryObject)
2583 {
Jamie Madill437fa652016-05-03 15:13:24 -04002584 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002585 return false;
2586 }
2587
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002588 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002589 {
Jamie Madill437fa652016-05-03 15:13:24 -04002590 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002591 return false;
2592 }
2593
2594 switch (pname)
2595 {
2596 case GL_QUERY_RESULT_EXT:
2597 case GL_QUERY_RESULT_AVAILABLE_EXT:
2598 break;
2599
2600 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002601 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002602 return false;
2603 }
2604
Geoff Lang2186c382016-10-14 10:54:54 -04002605 if (numParams)
2606 {
2607 *numParams = 1;
2608 }
2609
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002610 return true;
2611}
2612
2613bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2614{
2615 if (!context->getExtensions().disjointTimerQuery)
2616 {
Jamie Madill437fa652016-05-03 15:13:24 -04002617 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002618 return false;
2619 }
Geoff Lang2186c382016-10-14 10:54:54 -04002620 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2621}
2622
2623bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2624 GLuint id,
2625 GLenum pname,
2626 GLsizei bufSize,
2627 GLsizei *length,
2628 GLint *params)
2629{
2630 if (!context->getExtensions().disjointTimerQuery)
2631 {
2632 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2633 return false;
2634 }
2635
2636 if (!ValidateRobustEntryPoint(context, bufSize))
2637 {
2638 return false;
2639 }
2640
2641 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2642 {
2643 return false;
2644 }
2645
2646 if (!ValidateRobustBufferSize(context, bufSize, *length))
2647 {
2648 return false;
2649 }
2650
2651 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002652}
2653
2654bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2655{
2656 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002657 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002658 {
Jamie Madill437fa652016-05-03 15:13:24 -04002659 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002660 return false;
2661 }
Geoff Lang2186c382016-10-14 10:54:54 -04002662 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2663}
2664
2665bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2666 GLuint id,
2667 GLenum pname,
2668 GLsizei bufSize,
2669 GLsizei *length,
2670 GLuint *params)
2671{
2672 if (!context->getExtensions().disjointTimerQuery &&
2673 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2674 {
2675 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2676 return false;
2677 }
2678
2679 if (!ValidateRobustEntryPoint(context, bufSize))
2680 {
2681 return false;
2682 }
2683
2684 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2685 {
2686 return false;
2687 }
2688
2689 if (!ValidateRobustBufferSize(context, bufSize, *length))
2690 {
2691 return false;
2692 }
2693
2694 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002695}
2696
2697bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2698{
2699 if (!context->getExtensions().disjointTimerQuery)
2700 {
Jamie Madill437fa652016-05-03 15:13:24 -04002701 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002702 return false;
2703 }
Geoff Lang2186c382016-10-14 10:54:54 -04002704 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2705}
2706
2707bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2708 GLuint id,
2709 GLenum pname,
2710 GLsizei bufSize,
2711 GLsizei *length,
2712 GLint64 *params)
2713{
2714 if (!context->getExtensions().disjointTimerQuery)
2715 {
2716 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2717 return false;
2718 }
2719
2720 if (!ValidateRobustEntryPoint(context, bufSize))
2721 {
2722 return false;
2723 }
2724
2725 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2726 {
2727 return false;
2728 }
2729
2730 if (!ValidateRobustBufferSize(context, bufSize, *length))
2731 {
2732 return false;
2733 }
2734
2735 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002736}
2737
2738bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2739{
2740 if (!context->getExtensions().disjointTimerQuery)
2741 {
Jamie Madill437fa652016-05-03 15:13:24 -04002742 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002743 return false;
2744 }
Geoff Lang2186c382016-10-14 10:54:54 -04002745 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2746}
2747
2748bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2749 GLuint id,
2750 GLenum pname,
2751 GLsizei bufSize,
2752 GLsizei *length,
2753 GLuint64 *params)
2754{
2755 if (!context->getExtensions().disjointTimerQuery)
2756 {
2757 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2758 return false;
2759 }
2760
2761 if (!ValidateRobustEntryPoint(context, bufSize))
2762 {
2763 return false;
2764 }
2765
2766 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2767 {
2768 return false;
2769 }
2770
2771 if (!ValidateRobustBufferSize(context, bufSize, *length))
2772 {
2773 return false;
2774 }
2775
2776 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002777}
2778
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002779bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002780 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002781 GLuint program,
2782 GLint location,
2783 GLsizei count)
2784{
2785 // Check for ES31 program uniform entry points
2786 if (context->getClientVersion() < Version(3, 1))
2787 {
2788 context->handleError(Error(GL_INVALID_OPERATION));
2789 return false;
2790 }
2791
2792 const LinkedUniform *uniform = nullptr;
2793 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002794 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2795 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002796}
2797
Frank Henigmana98a6472017-02-02 21:38:32 -05002798bool ValidateProgramUniform1iv(gl::Context *context,
2799 GLuint program,
2800 GLint location,
2801 GLsizei count,
2802 const GLint *value)
2803{
2804 // Check for ES31 program uniform entry points
2805 if (context->getClientVersion() < Version(3, 1))
2806 {
2807 context->handleError(Error(GL_INVALID_OPERATION));
2808 return false;
2809 }
2810
2811 const LinkedUniform *uniform = nullptr;
2812 gl::Program *programObject = GetValidProgram(context, program);
2813 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2814 ValidateUniform1ivValue(context, uniform->type, count, value);
2815}
2816
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002817bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002818 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002819 GLuint program,
2820 GLint location,
2821 GLsizei count,
2822 GLboolean transpose)
2823{
2824 // Check for ES31 program uniform entry points
2825 if (context->getClientVersion() < Version(3, 1))
2826 {
2827 context->handleError(Error(GL_INVALID_OPERATION));
2828 return false;
2829 }
2830
2831 const LinkedUniform *uniform = nullptr;
2832 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002833 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2834 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002835}
2836
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002837bool ValidateUniform(gl::Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002838{
2839 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002840 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002841 {
Jamie Madill437fa652016-05-03 15:13:24 -04002842 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002843 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002844 }
2845
Jamie Madill62d31cb2015-09-11 13:25:51 -04002846 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002847 gl::Program *programObject = context->getGLState().getProgram();
2848 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2849 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002850}
2851
Frank Henigmana98a6472017-02-02 21:38:32 -05002852bool ValidateUniform1iv(gl::Context *context, GLint location, GLsizei count, const GLint *value)
2853{
2854 const LinkedUniform *uniform = nullptr;
2855 gl::Program *programObject = context->getGLState().getProgram();
2856 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2857 ValidateUniform1ivValue(context, uniform->type, count, value);
2858}
2859
He Yunchaoced53ae2016-11-29 15:00:51 +08002860bool ValidateUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002861 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002862 GLint location,
2863 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002864 GLboolean transpose)
2865{
2866 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002867 int rows = VariableRowCount(valueType);
2868 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002869 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002870 {
Jamie Madill437fa652016-05-03 15:13:24 -04002871 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002872 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002873 }
2874
Martin Radev1be913c2016-07-11 17:59:16 +03002875 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002876 {
Jamie Madill437fa652016-05-03 15:13:24 -04002877 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002878 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002879 }
2880
Jamie Madill62d31cb2015-09-11 13:25:51 -04002881 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002882 gl::Program *programObject = context->getGLState().getProgram();
2883 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2884 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002885}
2886
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002887bool ValidateStateQuery(ValidationContext *context,
2888 GLenum pname,
2889 GLenum *nativeType,
2890 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002891{
2892 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2893 {
Jamie Madill437fa652016-05-03 15:13:24 -04002894 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002895 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002896 }
2897
Jamie Madill0af26e12015-03-05 19:54:33 -05002898 const Caps &caps = context->getCaps();
2899
Jamie Madill893ab082014-05-16 16:56:10 -04002900 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2901 {
2902 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2903
Jamie Madill0af26e12015-03-05 19:54:33 -05002904 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002905 {
Jamie Madill437fa652016-05-03 15:13:24 -04002906 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002907 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002908 }
2909 }
2910
2911 switch (pname)
2912 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002913 case GL_TEXTURE_BINDING_2D:
2914 case GL_TEXTURE_BINDING_CUBE_MAP:
2915 case GL_TEXTURE_BINDING_3D:
2916 case GL_TEXTURE_BINDING_2D_ARRAY:
2917 break;
2918 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2919 if (!context->getExtensions().eglStreamConsumerExternal &&
2920 !context->getExtensions().eglImageExternal)
2921 {
2922 context->handleError(Error(GL_INVALID_ENUM,
2923 "Neither NV_EGL_stream_consumer_external nor "
2924 "GL_OES_EGL_image_external extensions enabled"));
2925 return false;
2926 }
2927 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002928
He Yunchaoced53ae2016-11-29 15:00:51 +08002929 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2930 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002931 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002932 if (context->getGLState().getReadFramebuffer()->checkStatus(
2933 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002934 {
Jamie Madill437fa652016-05-03 15:13:24 -04002935 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002936 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002937 }
2938
Jamie Madill51f40ec2016-06-15 14:06:00 -04002939 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2940 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002941
2942 if (framebuffer->getReadBufferState() == GL_NONE)
2943 {
2944 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2945 return false;
2946 }
2947
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002948 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002949 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002950 {
Jamie Madill437fa652016-05-03 15:13:24 -04002951 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002952 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002953 }
2954 }
2955 break;
2956
He Yunchaoced53ae2016-11-29 15:00:51 +08002957 default:
2958 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002959 }
2960
2961 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002962 if (*numParams == 0)
2963 {
2964 return false;
2965 }
2966
2967 return true;
2968}
2969
2970bool ValidateRobustStateQuery(ValidationContext *context,
2971 GLenum pname,
2972 GLsizei bufSize,
2973 GLenum *nativeType,
2974 unsigned int *numParams)
2975{
2976 if (!ValidateRobustEntryPoint(context, bufSize))
2977 {
2978 return false;
2979 }
2980
2981 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2982 {
2983 return false;
2984 }
2985
2986 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002987 {
2988 return false;
2989 }
2990
2991 return true;
2992}
2993
Jamie Madillc29968b2016-01-20 11:17:23 -05002994bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2995 GLenum target,
2996 GLint level,
2997 GLenum internalformat,
2998 bool isSubImage,
2999 GLint xoffset,
3000 GLint yoffset,
3001 GLint zoffset,
3002 GLint x,
3003 GLint y,
3004 GLsizei width,
3005 GLsizei height,
3006 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04003007 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04003008{
Jamie Madill560a8d82014-05-21 13:06:20 -04003009 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
3010 {
Jamie Madill437fa652016-05-03 15:13:24 -04003011 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003012 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003013 }
3014
He Yunchaoced53ae2016-11-29 15:00:51 +08003015 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3016 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04003017 {
Jamie Madill437fa652016-05-03 15:13:24 -04003018 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003019 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003020 }
3021
3022 if (border != 0)
3023 {
Jamie Madill437fa652016-05-03 15:13:24 -04003024 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003025 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003026 }
3027
3028 if (!ValidMipLevel(context, target, level))
3029 {
Jamie Madill437fa652016-05-03 15:13:24 -04003030 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003031 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003032 }
3033
Jamie Madill51f40ec2016-06-15 14:06:00 -04003034 const auto &state = context->getGLState();
3035 auto readFramebuffer = state.getReadFramebuffer();
3036 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003037 {
Jamie Madill437fa652016-05-03 15:13:24 -04003038 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003039 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003040 }
3041
Jamie Madill51f40ec2016-06-15 14:06:00 -04003042 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003043 {
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 Madill560a8d82014-05-21 13:06:20 -04003046 }
3047
Martin Radev138064f2016-07-15 12:03:41 +03003048 if (readFramebuffer->getReadBufferState() == GL_NONE)
3049 {
3050 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3051 return false;
3052 }
3053
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003054 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3055 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003056 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003057 // situation is an application error that would lead to a crash in ANGLE.
3058 if (readFramebuffer->getReadColorbuffer() == nullptr)
3059 {
3060 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3061 return false;
3062 }
3063
Geoff Langaae65a42014-05-26 12:43:44 -04003064 const gl::Caps &caps = context->getCaps();
3065
Geoff Langaae65a42014-05-26 12:43:44 -04003066 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003067 switch (target)
3068 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003069 case GL_TEXTURE_2D:
3070 maxDimension = caps.max2DTextureSize;
3071 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003072
He Yunchaoced53ae2016-11-29 15:00:51 +08003073 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3074 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3075 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3076 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3077 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3078 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3079 maxDimension = caps.maxCubeMapTextureSize;
3080 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003081
He Yunchaoced53ae2016-11-29 15:00:51 +08003082 case GL_TEXTURE_2D_ARRAY:
3083 maxDimension = caps.max2DTextureSize;
3084 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003085
He Yunchaoced53ae2016-11-29 15:00:51 +08003086 case GL_TEXTURE_3D:
3087 maxDimension = caps.max3DTextureSize;
3088 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003089
He Yunchaoced53ae2016-11-29 15:00:51 +08003090 default:
3091 context->handleError(Error(GL_INVALID_ENUM));
3092 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003093 }
3094
Jamie Madillc29968b2016-01-20 11:17:23 -05003095 gl::Texture *texture =
3096 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003097 if (!texture)
3098 {
Jamie Madill437fa652016-05-03 15:13:24 -04003099 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003100 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003101 }
3102
Geoff Lang69cce582015-09-17 13:20:36 -04003103 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003104 {
Jamie Madill437fa652016-05-03 15:13:24 -04003105 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003106 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003107 }
3108
Geoff Lang5d601382014-07-22 15:14:06 -04003109 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3110
3111 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003112 {
Jamie Madill437fa652016-05-03 15:13:24 -04003113 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003114 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003115 }
3116
Geoff Lang44ff5a72017-02-03 15:15:43 -05003117 if (formatInfo.compressed &&
3118 !ValidCompressedImageSize(context, internalformat, xoffset, yoffset, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003119 {
Jamie Madill437fa652016-05-03 15:13:24 -04003120 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003121 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003122 }
3123
3124 if (isSubImage)
3125 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003126 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3127 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3128 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003129 {
Jamie Madill437fa652016-05-03 15:13:24 -04003130 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003131 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003132 }
3133 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003134 else
3135 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003136 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003137 {
Jamie Madill437fa652016-05-03 15:13:24 -04003138 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003139 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003140 }
3141
Geoff Langeb66a6e2016-10-31 13:06:12 -04003142 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003143 {
Jamie Madill437fa652016-05-03 15:13:24 -04003144 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003145 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003146 }
3147
3148 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003149 if (static_cast<int>(width) > maxLevelDimension ||
3150 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003151 {
Jamie Madill437fa652016-05-03 15:13:24 -04003152 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003153 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003154 }
3155 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003156
Jamie Madill0c8abca2016-07-22 20:21:26 -04003157 if (textureFormatOut)
3158 {
3159 *textureFormatOut = texture->getFormat(target, level);
3160 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003161
3162 // Detect texture copying feedback loops for WebGL.
3163 if (context->getExtensions().webglCompatibility)
3164 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05003165 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05003166 {
3167 context->handleError(Error(GL_INVALID_OPERATION,
3168 "Texture copying feedback loop formed between Framebuffer "
3169 "and specified Texture level."));
3170 return false;
3171 }
3172 }
3173
Jamie Madill560a8d82014-05-21 13:06:20 -04003174 return true;
3175}
3176
Jiajia Qind9671222016-11-29 16:30:31 +08003177bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003178{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003179 switch (mode)
3180 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003181 case GL_POINTS:
3182 case GL_LINES:
3183 case GL_LINE_LOOP:
3184 case GL_LINE_STRIP:
3185 case GL_TRIANGLES:
3186 case GL_TRIANGLE_STRIP:
3187 case GL_TRIANGLE_FAN:
3188 break;
3189 default:
3190 context->handleError(Error(GL_INVALID_ENUM));
3191 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003192 }
3193
Jamie Madill250d33f2014-06-06 17:09:03 -04003194 if (count < 0)
3195 {
Jamie Madill437fa652016-05-03 15:13:24 -04003196 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003197 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003198 }
3199
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003200 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003201
Jamie Madill250d33f2014-06-06 17:09:03 -04003202 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003203 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003204 {
Jamie Madill437fa652016-05-03 15:13:24 -04003205 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003206 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003207 }
3208
Jamie Madillcbcde722017-01-06 14:50:00 -05003209 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3210 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003211 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003212 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3213 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003214 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003215 const FramebufferAttachment *dsAttachment =
3216 framebuffer->getStencilOrDepthStencilAttachment();
3217 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003218 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003219 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003220
3221 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3222 bool differentWritemasks =
3223 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3224 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3225 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3226 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3227
3228 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003229 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003230 if (!context->getExtensions().webglCompatibility)
3231 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003232 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3233 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003234 }
Jamie Madill437fa652016-05-03 15:13:24 -04003235 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003236 return false;
3237 }
Jamie Madillac528012014-06-20 13:21:23 -04003238 }
3239
Jamie Madill51f40ec2016-06-15 14:06:00 -04003240 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003241 {
Jamie Madill437fa652016-05-03 15:13:24 -04003242 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003243 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003244 }
3245
Geoff Lang7dd2e102014-11-10 15:19:26 -05003246 gl::Program *program = state.getProgram();
3247 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003248 {
Jamie Madill437fa652016-05-03 15:13:24 -04003249 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003250 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003251 }
3252
Geoff Lang7dd2e102014-11-10 15:19:26 -05003253 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003254 {
Jamie Madill437fa652016-05-03 15:13:24 -04003255 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003256 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003257 }
3258
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003259 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003260 for (unsigned int uniformBlockIndex = 0;
3261 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003262 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003263 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003264 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003265 const OffsetBindingPointer<Buffer> &uniformBuffer =
3266 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003267
Geoff Lang5d124a62015-09-15 13:03:27 -04003268 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003269 {
3270 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003271 context->handleError(
3272 Error(GL_INVALID_OPERATION,
3273 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003274 return false;
3275 }
3276
Geoff Lang5d124a62015-09-15 13:03:27 -04003277 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003278 if (uniformBufferSize == 0)
3279 {
3280 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003281 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003282 }
3283
Jamie Madill62d31cb2015-09-11 13:25:51 -04003284 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003285 {
3286 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003287 context->handleError(
3288 Error(GL_INVALID_OPERATION,
3289 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003290 return false;
3291 }
3292 }
3293
Jamie Madilla4595b82017-01-11 17:36:34 -05003294 // Detect rendering feedback loops for WebGL.
3295 if (context->getExtensions().webglCompatibility)
3296 {
3297 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3298 {
3299 context->handleError(
3300 Error(GL_INVALID_OPERATION,
3301 "Rendering feedback loop formed between Framebuffer and active Texture."));
3302 return false;
3303 }
3304 }
3305
Jamie Madill250d33f2014-06-06 17:09:03 -04003306 // No-op if zero count
3307 return (count > 0);
3308}
3309
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003310bool ValidateDrawArrays(ValidationContext *context,
3311 GLenum mode,
3312 GLint first,
3313 GLsizei count,
3314 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003315{
Jamie Madillfd716582014-06-06 17:09:04 -04003316 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003317 {
Jamie Madill437fa652016-05-03 15:13:24 -04003318 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003319 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003320 }
3321
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003322 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003323 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003324 if (curTransformFeedback && curTransformFeedback->isActive() &&
3325 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003326 {
3327 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003328 // that does not match the current transform feedback object's draw mode (if transform
3329 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003330 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003331 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003332 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003333 }
3334
Jiajia Qind9671222016-11-29 16:30:31 +08003335 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003336 {
3337 return false;
3338 }
3339
Corentin Wallez71168a02016-12-19 15:11:18 -08003340 // Check the computation of maxVertex doesn't overflow.
3341 // - first < 0 or count < 0 have been checked as an error condition
3342 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3343 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3344 ASSERT(count > 0 && first >= 0);
3345 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3346 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003347 {
3348 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3349 return false;
3350 }
3351
Corentin Wallez71168a02016-12-19 15:11:18 -08003352 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003353 {
3354 return false;
3355 }
3356
3357 return true;
3358}
3359
He Yunchaoced53ae2016-11-29 15:00:51 +08003360bool ValidateDrawArraysInstanced(Context *context,
3361 GLenum mode,
3362 GLint first,
3363 GLsizei count,
3364 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003365{
3366 if (primcount < 0)
3367 {
Jamie Madill437fa652016-05-03 15:13:24 -04003368 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003369 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003370 }
3371
Jamie Madill2b976812014-08-25 15:47:49 -04003372 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003373 {
3374 return false;
3375 }
3376
3377 // No-op if zero primitive count
3378 return (primcount > 0);
3379}
3380
Geoff Lang87a93302014-09-16 13:29:43 -04003381static bool ValidateDrawInstancedANGLE(Context *context)
3382{
3383 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003384 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003385
Geoff Lang7dd2e102014-11-10 15:19:26 -05003386 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003387
3388 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003389 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003390 {
3391 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003392 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003393 {
3394 return true;
3395 }
3396 }
3397
Jamie Madill437fa652016-05-03 15:13:24 -04003398 context->handleError(Error(GL_INVALID_OPERATION,
3399 "ANGLE_instanced_arrays requires that at least one active attribute"
3400 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003401 return false;
3402}
3403
He Yunchaoced53ae2016-11-29 15:00:51 +08003404bool ValidateDrawArraysInstancedANGLE(Context *context,
3405 GLenum mode,
3406 GLint first,
3407 GLsizei count,
3408 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003409{
3410 if (!ValidateDrawInstancedANGLE(context))
3411 {
3412 return false;
3413 }
3414
3415 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3416}
3417
Jiajia Qind9671222016-11-29 16:30:31 +08003418bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003419{
Jamie Madill250d33f2014-06-06 17:09:03 -04003420 switch (type)
3421 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003422 case GL_UNSIGNED_BYTE:
3423 case GL_UNSIGNED_SHORT:
3424 break;
3425 case GL_UNSIGNED_INT:
3426 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3427 {
3428 context->handleError(Error(GL_INVALID_ENUM));
3429 return false;
3430 }
3431 break;
3432 default:
3433 context->handleError(Error(GL_INVALID_ENUM));
3434 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003435 }
3436
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003437 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003438
3439 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003440 if (curTransformFeedback && curTransformFeedback->isActive() &&
3441 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003442 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003443 // It is an invalid operation to call DrawElements, DrawRangeElements or
3444 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003445 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003446 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003447 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003448 }
3449
Jiajia Qind9671222016-11-29 16:30:31 +08003450 return true;
3451}
3452
3453bool ValidateDrawElements(ValidationContext *context,
3454 GLenum mode,
3455 GLsizei count,
3456 GLenum type,
3457 const GLvoid *indices,
3458 GLsizei primcount,
3459 IndexRange *indexRangeOut)
3460{
3461 if (!ValidateDrawElementsBase(context, type))
3462 return false;
3463
3464 const State &state = context->getGLState();
3465
Jamie Madill250d33f2014-06-06 17:09:03 -04003466 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003467 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003468 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003469 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04003470 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003471 }
3472
He Yunchaoced53ae2016-11-29 15:00:51 +08003473 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003474 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003475
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003476 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3477
3478 if (context->getExtensions().webglCompatibility)
3479 {
3480 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3481 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3482 {
3483 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3484 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3485 // data type passed to the call, or an INVALID_OPERATION error is generated.
3486 context->handleError(Error(GL_INVALID_OPERATION,
3487 "indices must be a multiple of the element type size."));
3488 return false;
3489 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003490 }
3491
3492 if (context->getExtensions().webglCompatibility ||
3493 !context->getGLState().areClientArraysEnabled())
3494 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003495 if (!elementArrayBuffer && count > 0)
3496 {
3497 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3498 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3499 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3500 context->handleError(Error(GL_INVALID_OPERATION,
3501 "There is no element array buffer bound and count > 0."));
3502 return false;
3503 }
3504 }
3505
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003506 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003507 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003508 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003509 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003510 GLint64 offset = reinterpret_cast<GLint64>(indices);
3511 GLint64 byteCount =
3512 static_cast<GLint64>(typeBytes) * static_cast<GLint64>(count) + offset;
3513
3514 // check for integer overflows
3515 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeBytes) ||
3516 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3517 {
3518 context->handleError(Error(GL_OUT_OF_MEMORY, "Integer overflow."));
3519 return false;
3520 }
3521
3522 // Check for reading past the end of the bound buffer object
3523 if (byteCount > elementArrayBuffer->getSize())
3524 {
3525 context->handleError(
3526 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
3527 return false;
3528 }
3529 }
3530 else if (!indices)
3531 {
3532 // This is an application error that would normally result in a crash,
3533 // but we catch it and return an error
3534 context->handleError(
3535 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003536 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003537 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003538 }
3539
Jiajia Qind9671222016-11-29 16:30:31 +08003540 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003541 {
3542 return false;
3543 }
3544
Jamie Madill2b976812014-08-25 15:47:49 -04003545 // Use max index to validate if our vertex buffers are large enough for the pull.
3546 // TODO: offer fast path, with disabled index validation.
3547 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3548 if (elementArrayBuffer)
3549 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003550 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003551 Error error =
3552 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3553 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003554 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003555 {
Jamie Madill437fa652016-05-03 15:13:24 -04003556 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003557 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003558 }
3559 }
3560 else
3561 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003562 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003563 }
3564
Jamie Madille79b1e12015-11-04 16:36:37 -05003565 // If we use an index greater than our maximum supported index range, return an error.
3566 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3567 // return an error if possible here.
3568 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3569 {
Jamie Madill437fa652016-05-03 15:13:24 -04003570 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003571 return false;
3572 }
3573
Corentin Wallez92db6942016-12-09 13:10:36 -05003574 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3575 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003576 {
3577 return false;
3578 }
3579
Geoff Lang3edfe032015-09-04 16:38:24 -04003580 // No op if there are no real indices in the index data (all are primitive restart).
3581 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003582}
3583
Geoff Langb1196682014-07-23 13:47:29 -04003584bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003585 GLenum mode,
3586 GLsizei count,
3587 GLenum type,
3588 const GLvoid *indices,
3589 GLsizei primcount,
3590 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003591{
3592 if (primcount < 0)
3593 {
Jamie Madill437fa652016-05-03 15:13:24 -04003594 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003595 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003596 }
3597
Jamie Madill2b976812014-08-25 15:47:49 -04003598 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003599 {
3600 return false;
3601 }
3602
3603 // No-op zero primitive count
3604 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003605}
3606
Geoff Lang3edfe032015-09-04 16:38:24 -04003607bool ValidateDrawElementsInstancedANGLE(Context *context,
3608 GLenum mode,
3609 GLsizei count,
3610 GLenum type,
3611 const GLvoid *indices,
3612 GLsizei primcount,
3613 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003614{
3615 if (!ValidateDrawInstancedANGLE(context))
3616 {
3617 return false;
3618 }
3619
He Yunchaoced53ae2016-11-29 15:00:51 +08003620 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3621 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003622}
3623
He Yunchaoced53ae2016-11-29 15:00:51 +08003624bool ValidateFramebufferTextureBase(Context *context,
3625 GLenum target,
3626 GLenum attachment,
3627 GLuint texture,
3628 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003629{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003630 if (!ValidFramebufferTarget(target))
3631 {
Jamie Madill437fa652016-05-03 15:13:24 -04003632 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003633 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003634 }
3635
3636 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003637 {
3638 return false;
3639 }
3640
Jamie Madill55ec3b12014-07-03 10:38:57 -04003641 if (texture != 0)
3642 {
3643 gl::Texture *tex = context->getTexture(texture);
3644
3645 if (tex == NULL)
3646 {
Jamie Madill437fa652016-05-03 15:13:24 -04003647 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003648 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003649 }
3650
3651 if (level < 0)
3652 {
Jamie Madill437fa652016-05-03 15:13:24 -04003653 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003654 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003655 }
3656 }
3657
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003658 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003659 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003660
Jamie Madill84115c92015-04-23 15:00:07 -04003661 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003662 {
Jamie Madill437fa652016-05-03 15:13:24 -04003663 context->handleError(
3664 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003665 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003666 }
3667
3668 return true;
3669}
3670
He Yunchaoced53ae2016-11-29 15:00:51 +08003671bool ValidateFramebufferTexture2D(Context *context,
3672 GLenum target,
3673 GLenum attachment,
3674 GLenum textarget,
3675 GLuint texture,
3676 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003677{
He Yunchaoced53ae2016-11-29 15:00:51 +08003678 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3679 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003680 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3681 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003682 {
Jamie Madill437fa652016-05-03 15:13:24 -04003683 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003684 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003685 }
3686
3687 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003688 {
3689 return false;
3690 }
3691
Jamie Madill55ec3b12014-07-03 10:38:57 -04003692 if (texture != 0)
3693 {
3694 gl::Texture *tex = context->getTexture(texture);
3695 ASSERT(tex);
3696
Jamie Madill2a6564e2014-07-11 09:53:19 -04003697 const gl::Caps &caps = context->getCaps();
3698
Jamie Madill55ec3b12014-07-03 10:38:57 -04003699 switch (textarget)
3700 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003701 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003702 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003703 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003704 {
Jamie Madill437fa652016-05-03 15:13:24 -04003705 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003706 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003707 }
3708 if (tex->getTarget() != GL_TEXTURE_2D)
3709 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003710 context->handleError(Error(GL_INVALID_OPERATION,
3711 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003712 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003713 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003714 }
3715 break;
3716
He Yunchaoced53ae2016-11-29 15:00:51 +08003717 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3718 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3719 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3720 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3721 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3722 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003723 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003724 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003725 {
Jamie Madill437fa652016-05-03 15:13:24 -04003726 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003727 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003728 }
3729 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3730 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003731 context->handleError(Error(GL_INVALID_OPERATION,
3732 "Textarget must match the texture target type."));
3733 return false;
3734 }
3735 }
3736 break;
3737
3738 case GL_TEXTURE_2D_MULTISAMPLE:
3739 {
3740 if (context->getClientVersion() < ES_3_1)
3741 {
3742 context->handleError(Error(GL_INVALID_OPERATION,
3743 "Texture target requires at least OpenGL ES 3.1."));
3744 return false;
3745 }
3746
3747 if (level != 0)
3748 {
3749 context->handleError(
3750 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
3751 return false;
3752 }
3753 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
3754 {
3755 context->handleError(Error(GL_INVALID_OPERATION,
3756 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003757 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003758 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003759 }
3760 break;
3761
He Yunchaoced53ae2016-11-29 15:00:51 +08003762 default:
3763 context->handleError(Error(GL_INVALID_ENUM));
3764 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003765 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003766
Jamie Madilla3944d42016-07-22 22:13:26 -04003767 const Format &format = tex->getFormat(textarget, level);
3768 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003769 {
Jamie Madill437fa652016-05-03 15:13:24 -04003770 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003771 return false;
3772 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003773 }
3774
Jamie Madill570f7c82014-07-03 10:38:54 -04003775 return true;
3776}
3777
Geoff Langb1196682014-07-23 13:47:29 -04003778bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003779{
3780 if (program == 0)
3781 {
Jamie Madill437fa652016-05-03 15:13:24 -04003782 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003783 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003784 }
3785
Dian Xiang769769a2015-09-09 15:20:08 -07003786 gl::Program *programObject = GetValidProgram(context, program);
3787 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003788 {
3789 return false;
3790 }
3791
Jamie Madill0063c512014-08-25 15:47:53 -04003792 if (!programObject || !programObject->isLinked())
3793 {
Jamie Madill437fa652016-05-03 15:13:24 -04003794 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003795 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003796 }
3797
Geoff Lang7dd2e102014-11-10 15:19:26 -05003798 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003799 {
Jamie Madill437fa652016-05-03 15:13:24 -04003800 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003801 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003802 }
3803
Jamie Madill0063c512014-08-25 15:47:53 -04003804 return true;
3805}
3806
He Yunchaoced53ae2016-11-29 15:00:51 +08003807bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003808{
3809 return ValidateGetUniformBase(context, program, location);
3810}
3811
He Yunchaoced53ae2016-11-29 15:00:51 +08003812bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003813{
Jamie Madill78f41802014-08-25 15:47:55 -04003814 return ValidateGetUniformBase(context, program, location);
3815}
3816
Geoff Langf41d0ee2016-10-07 13:04:23 -04003817static bool ValidateSizedGetUniform(Context *context,
3818 GLuint program,
3819 GLint location,
3820 GLsizei bufSize,
3821 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003822{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003823 if (length)
3824 {
3825 *length = 0;
3826 }
3827
Jamie Madill78f41802014-08-25 15:47:55 -04003828 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003829 {
Jamie Madill78f41802014-08-25 15:47:55 -04003830 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003831 }
3832
Geoff Langf41d0ee2016-10-07 13:04:23 -04003833 if (bufSize < 0)
3834 {
3835 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3836 return false;
3837 }
3838
Jamie Madilla502c742014-08-28 17:19:13 -04003839 gl::Program *programObject = context->getProgram(program);
3840 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003841
Jamie Madill78f41802014-08-25 15:47:55 -04003842 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003843 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003844 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003845 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003846 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003847 context->handleError(
3848 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003849 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003850 }
3851
Geoff Langf41d0ee2016-10-07 13:04:23 -04003852 if (length)
3853 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003854 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003855 }
3856
Jamie Madill0063c512014-08-25 15:47:53 -04003857 return true;
3858}
3859
He Yunchaoced53ae2016-11-29 15:00:51 +08003860bool ValidateGetnUniformfvEXT(Context *context,
3861 GLuint program,
3862 GLint location,
3863 GLsizei bufSize,
3864 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003865{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003866 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003867}
3868
He Yunchaoced53ae2016-11-29 15:00:51 +08003869bool ValidateGetnUniformivEXT(Context *context,
3870 GLuint program,
3871 GLint location,
3872 GLsizei bufSize,
3873 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003874{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003875 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3876}
3877
3878bool ValidateGetUniformfvRobustANGLE(Context *context,
3879 GLuint program,
3880 GLint location,
3881 GLsizei bufSize,
3882 GLsizei *length,
3883 GLfloat *params)
3884{
3885 if (!ValidateRobustEntryPoint(context, bufSize))
3886 {
3887 return false;
3888 }
3889
3890 // bufSize is validated in ValidateSizedGetUniform
3891 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3892}
3893
3894bool ValidateGetUniformivRobustANGLE(Context *context,
3895 GLuint program,
3896 GLint location,
3897 GLsizei bufSize,
3898 GLsizei *length,
3899 GLint *params)
3900{
3901 if (!ValidateRobustEntryPoint(context, bufSize))
3902 {
3903 return false;
3904 }
3905
3906 // bufSize is validated in ValidateSizedGetUniform
3907 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3908}
3909
3910bool ValidateGetUniformuivRobustANGLE(Context *context,
3911 GLuint program,
3912 GLint location,
3913 GLsizei bufSize,
3914 GLsizei *length,
3915 GLuint *params)
3916{
3917 if (!ValidateRobustEntryPoint(context, bufSize))
3918 {
3919 return false;
3920 }
3921
3922 if (context->getClientMajorVersion() < 3)
3923 {
3924 context->handleError(
3925 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3926 return false;
3927 }
3928
3929 // bufSize is validated in ValidateSizedGetUniform
3930 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003931}
3932
He Yunchaoced53ae2016-11-29 15:00:51 +08003933bool ValidateDiscardFramebufferBase(Context *context,
3934 GLenum target,
3935 GLsizei numAttachments,
3936 const GLenum *attachments,
3937 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003938{
3939 if (numAttachments < 0)
3940 {
Jamie Madill437fa652016-05-03 15:13:24 -04003941 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003942 return false;
3943 }
3944
3945 for (GLsizei i = 0; i < numAttachments; ++i)
3946 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003947 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003948 {
3949 if (defaultFramebuffer)
3950 {
Jamie Madill437fa652016-05-03 15:13:24 -04003951 context->handleError(Error(
3952 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003953 return false;
3954 }
3955
3956 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3957 {
Jamie Madill437fa652016-05-03 15:13:24 -04003958 context->handleError(Error(GL_INVALID_OPERATION,
3959 "Requested color attachment is greater than the maximum "
3960 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003961 return false;
3962 }
3963 }
3964 else
3965 {
3966 switch (attachments[i])
3967 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003968 case GL_DEPTH_ATTACHMENT:
3969 case GL_STENCIL_ATTACHMENT:
3970 case GL_DEPTH_STENCIL_ATTACHMENT:
3971 if (defaultFramebuffer)
3972 {
3973 context->handleError(
3974 Error(GL_INVALID_ENUM,
3975 "Invalid attachment when the default framebuffer is bound"));
3976 return false;
3977 }
3978 break;
3979 case GL_COLOR:
3980 case GL_DEPTH:
3981 case GL_STENCIL:
3982 if (!defaultFramebuffer)
3983 {
3984 context->handleError(
3985 Error(GL_INVALID_ENUM,
3986 "Invalid attachment when the default framebuffer is not bound"));
3987 return false;
3988 }
3989 break;
3990 default:
3991 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003992 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003993 }
3994 }
3995 }
3996
3997 return true;
3998}
3999
Austin Kinross6ee1e782015-05-29 17:05:37 -07004000bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
4001{
4002 // Note that debug marker calls must not set error state
4003
4004 if (length < 0)
4005 {
4006 return false;
4007 }
4008
4009 if (marker == nullptr)
4010 {
4011 return false;
4012 }
4013
4014 return true;
4015}
4016
4017bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
4018{
4019 // Note that debug marker calls must not set error state
4020
4021 if (length < 0)
4022 {
4023 return false;
4024 }
4025
4026 if (length > 0 && marker == nullptr)
4027 {
4028 return false;
4029 }
4030
4031 return true;
4032}
4033
Geoff Langdcab33b2015-07-21 13:03:16 -04004034bool ValidateEGLImageTargetTexture2DOES(Context *context,
4035 egl::Display *display,
4036 GLenum target,
4037 egl::Image *image)
4038{
Geoff Langa8406172015-07-21 16:53:39 -04004039 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4040 {
Jamie Madill437fa652016-05-03 15:13:24 -04004041 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004042 return false;
4043 }
4044
4045 switch (target)
4046 {
4047 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004048 if (!context->getExtensions().eglImage)
4049 {
4050 context->handleError(Error(
4051 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4052 }
4053 break;
4054
4055 case GL_TEXTURE_EXTERNAL_OES:
4056 if (!context->getExtensions().eglImageExternal)
4057 {
4058 context->handleError(Error(
4059 GL_INVALID_ENUM,
4060 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4061 }
Geoff Langa8406172015-07-21 16:53:39 -04004062 break;
4063
4064 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004065 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004066 return false;
4067 }
4068
4069 if (!display->isValidImage(image))
4070 {
Jamie Madill437fa652016-05-03 15:13:24 -04004071 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004072 return false;
4073 }
4074
4075 if (image->getSamples() > 0)
4076 {
Jamie Madill437fa652016-05-03 15:13:24 -04004077 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004078 "cannot create a 2D texture from a multisampled EGL image."));
4079 return false;
4080 }
4081
Jamie Madilla3944d42016-07-22 22:13:26 -04004082 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004083 if (!textureCaps.texturable)
4084 {
Jamie Madill437fa652016-05-03 15:13:24 -04004085 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004086 "EGL image internal format is not supported as a texture."));
4087 return false;
4088 }
4089
Geoff Langdcab33b2015-07-21 13:03:16 -04004090 return true;
4091}
4092
4093bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4094 egl::Display *display,
4095 GLenum target,
4096 egl::Image *image)
4097{
Geoff Langa8406172015-07-21 16:53:39 -04004098 if (!context->getExtensions().eglImage)
4099 {
Jamie Madill437fa652016-05-03 15:13:24 -04004100 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004101 return false;
4102 }
4103
4104 switch (target)
4105 {
4106 case GL_RENDERBUFFER:
4107 break;
4108
4109 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004110 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004111 return false;
4112 }
4113
4114 if (!display->isValidImage(image))
4115 {
Jamie Madill437fa652016-05-03 15:13:24 -04004116 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004117 return false;
4118 }
4119
Jamie Madilla3944d42016-07-22 22:13:26 -04004120 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004121 if (!textureCaps.renderable)
4122 {
Jamie Madill437fa652016-05-03 15:13:24 -04004123 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004124 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4125 return false;
4126 }
4127
Geoff Langdcab33b2015-07-21 13:03:16 -04004128 return true;
4129}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004130
4131bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4132{
Geoff Lang36167ab2015-12-07 10:27:14 -05004133 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004134 {
4135 // The default VAO should always exist
4136 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004137 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004138 return false;
4139 }
4140
4141 return true;
4142}
4143
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004144bool ValidateLinkProgram(Context *context, GLuint program)
4145{
4146 if (context->hasActiveTransformFeedback(program))
4147 {
4148 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004149 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004150 "Cannot link program while program is associated with an active "
4151 "transform feedback object."));
4152 return false;
4153 }
4154 return true;
4155}
4156
Geoff Langc5629752015-12-07 16:29:04 -05004157bool ValidateProgramBinaryBase(Context *context,
4158 GLuint program,
4159 GLenum binaryFormat,
4160 const void *binary,
4161 GLint length)
4162{
4163 Program *programObject = GetValidProgram(context, program);
4164 if (programObject == nullptr)
4165 {
4166 return false;
4167 }
4168
4169 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4170 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4171 programBinaryFormats.end())
4172 {
Jamie Madill437fa652016-05-03 15:13:24 -04004173 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004174 return false;
4175 }
4176
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004177 if (context->hasActiveTransformFeedback(program))
4178 {
4179 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004180 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004181 "Cannot change program binary while program is associated with "
4182 "an active transform feedback object."));
4183 return false;
4184 }
4185
Geoff Langc5629752015-12-07 16:29:04 -05004186 return true;
4187}
4188
4189bool ValidateGetProgramBinaryBase(Context *context,
4190 GLuint program,
4191 GLsizei bufSize,
4192 GLsizei *length,
4193 GLenum *binaryFormat,
4194 void *binary)
4195{
4196 Program *programObject = GetValidProgram(context, program);
4197 if (programObject == nullptr)
4198 {
4199 return false;
4200 }
4201
4202 if (!programObject->isLinked())
4203 {
Jamie Madill437fa652016-05-03 15:13:24 -04004204 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004205 return false;
4206 }
4207
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004208 if (context->getCaps().programBinaryFormats.empty())
4209 {
4210 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4211 return false;
4212 }
4213
Geoff Langc5629752015-12-07 16:29:04 -05004214 return true;
4215}
Jamie Madillc29968b2016-01-20 11:17:23 -05004216
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004217bool ValidateUseProgram(Context *context, GLuint program)
4218{
4219 if (program != 0)
4220 {
4221 Program *programObject = context->getProgram(program);
4222 if (!programObject)
4223 {
4224 // ES 3.1.0 section 7.3 page 72
4225 if (context->getShader(program))
4226 {
Jamie Madill437fa652016-05-03 15:13:24 -04004227 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004228 Error(GL_INVALID_OPERATION,
4229 "Attempted to use a single shader instead of a shader program."));
4230 return false;
4231 }
4232 else
4233 {
Jamie Madill437fa652016-05-03 15:13:24 -04004234 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004235 return false;
4236 }
4237 }
4238 if (!programObject->isLinked())
4239 {
Jamie Madill437fa652016-05-03 15:13:24 -04004240 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004241 return false;
4242 }
4243 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004244 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004245 {
4246 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004247 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004248 Error(GL_INVALID_OPERATION,
4249 "Cannot change active program while transform feedback is unpaused."));
4250 return false;
4251 }
4252
4253 return true;
4254}
4255
Jamie Madillc29968b2016-01-20 11:17:23 -05004256bool ValidateCopyTexImage2D(ValidationContext *context,
4257 GLenum target,
4258 GLint level,
4259 GLenum internalformat,
4260 GLint x,
4261 GLint y,
4262 GLsizei width,
4263 GLsizei height,
4264 GLint border)
4265{
Martin Radev1be913c2016-07-11 17:59:16 +03004266 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004267 {
4268 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4269 0, x, y, width, height, border);
4270 }
4271
Martin Radev1be913c2016-07-11 17:59:16 +03004272 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004273 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4274 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004275}
Jamie Madillc29968b2016-01-20 11:17:23 -05004276
4277bool ValidateFramebufferRenderbuffer(Context *context,
4278 GLenum target,
4279 GLenum attachment,
4280 GLenum renderbuffertarget,
4281 GLuint renderbuffer)
4282{
4283 if (!ValidFramebufferTarget(target) ||
4284 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4285 {
Jamie Madill437fa652016-05-03 15:13:24 -04004286 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004287 return false;
4288 }
4289
4290 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4291 renderbuffertarget, renderbuffer);
4292}
4293
4294bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4295{
4296 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4297 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4298 {
Jamie Madill437fa652016-05-03 15:13:24 -04004299 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004300 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4301 return false;
4302 }
4303
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004304 ASSERT(context->getGLState().getDrawFramebuffer());
4305 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004306 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4307
4308 // This should come first before the check for the default frame buffer
4309 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4310 // rather than INVALID_OPERATION
4311 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4312 {
4313 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4314
4315 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004316 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4317 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004318 {
4319 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004320 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4321 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4322 // 3.1 is still a bit ambiguous about the error, but future specs are
4323 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004324 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004325 return false;
4326 }
4327 else if (bufs[colorAttachment] >= maxColorAttachment)
4328 {
Jamie Madill437fa652016-05-03 15:13:24 -04004329 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004330 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004331 return false;
4332 }
4333 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4334 frameBufferId != 0)
4335 {
4336 // INVALID_OPERATION-GL is bound to buffer and ith argument
4337 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004338 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004339 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4340 return false;
4341 }
4342 }
4343
4344 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4345 // and n is not 1 or bufs is bound to value other than BACK and NONE
4346 if (frameBufferId == 0)
4347 {
4348 if (n != 1)
4349 {
Jamie Madill437fa652016-05-03 15:13:24 -04004350 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004351 "n must be 1 when GL is bound to the default framebuffer"));
4352 return false;
4353 }
4354
4355 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4356 {
Jamie Madill437fa652016-05-03 15:13:24 -04004357 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004358 GL_INVALID_OPERATION,
4359 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4360 return false;
4361 }
4362 }
4363
4364 return true;
4365}
4366
4367bool ValidateCopyTexSubImage2D(Context *context,
4368 GLenum target,
4369 GLint level,
4370 GLint xoffset,
4371 GLint yoffset,
4372 GLint x,
4373 GLint y,
4374 GLsizei width,
4375 GLsizei height)
4376{
Martin Radev1be913c2016-07-11 17:59:16 +03004377 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004378 {
4379 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4380 yoffset, x, y, width, height, 0);
4381 }
4382
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004383 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4384 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004385}
4386
Geoff Lang496c02d2016-10-20 11:38:11 -07004387bool ValidateGetBufferPointervBase(Context *context,
4388 GLenum target,
4389 GLenum pname,
4390 GLsizei *length,
4391 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004392{
Geoff Lang496c02d2016-10-20 11:38:11 -07004393 if (length)
4394 {
4395 *length = 0;
4396 }
4397
4398 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4399 {
4400 context->handleError(
4401 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004402 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004403 return false;
4404 }
4405
Olli Etuaho4f667482016-03-30 15:56:35 +03004406 if (!ValidBufferTarget(context, target))
4407 {
Jamie Madill437fa652016-05-03 15:13:24 -04004408 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004409 return false;
4410 }
4411
Geoff Lang496c02d2016-10-20 11:38:11 -07004412 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004413 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004414 case GL_BUFFER_MAP_POINTER:
4415 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004416
Geoff Lang496c02d2016-10-20 11:38:11 -07004417 default:
4418 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4419 return false;
4420 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004421
4422 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4423 // target bound to zero generate an INVALID_OPERATION error."
4424 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004425 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004426 {
Jamie Madill437fa652016-05-03 15:13:24 -04004427 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004428 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4429 return false;
4430 }
4431
Geoff Lang496c02d2016-10-20 11:38:11 -07004432 if (length)
4433 {
4434 *length = 1;
4435 }
4436
Olli Etuaho4f667482016-03-30 15:56:35 +03004437 return true;
4438}
4439
4440bool ValidateUnmapBufferBase(Context *context, GLenum target)
4441{
4442 if (!ValidBufferTarget(context, target))
4443 {
Jamie Madill437fa652016-05-03 15:13:24 -04004444 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004445 return false;
4446 }
4447
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004448 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004449
4450 if (buffer == nullptr || !buffer->isMapped())
4451 {
Jamie Madill437fa652016-05-03 15:13:24 -04004452 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004453 return false;
4454 }
4455
4456 return true;
4457}
4458
4459bool ValidateMapBufferRangeBase(Context *context,
4460 GLenum target,
4461 GLintptr offset,
4462 GLsizeiptr length,
4463 GLbitfield access)
4464{
4465 if (!ValidBufferTarget(context, target))
4466 {
Jamie Madill437fa652016-05-03 15:13:24 -04004467 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004468 return false;
4469 }
4470
4471 if (offset < 0 || length < 0)
4472 {
Jamie Madill437fa652016-05-03 15:13:24 -04004473 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004474 return false;
4475 }
4476
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004477 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004478
4479 if (!buffer)
4480 {
Jamie Madill437fa652016-05-03 15:13:24 -04004481 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004482 return false;
4483 }
4484
4485 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004486 CheckedNumeric<size_t> checkedOffset(offset);
4487 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004488
Jamie Madille2e406c2016-06-02 13:04:10 -04004489 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004490 {
Jamie Madill437fa652016-05-03 15:13:24 -04004491 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004492 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4493 return false;
4494 }
4495
4496 // Check for invalid bits in the mask
4497 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4498 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4499 GL_MAP_UNSYNCHRONIZED_BIT;
4500
4501 if (access & ~(allAccessBits))
4502 {
Jamie Madill437fa652016-05-03 15:13:24 -04004503 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004504 return false;
4505 }
4506
4507 if (length == 0)
4508 {
Jamie Madill437fa652016-05-03 15:13:24 -04004509 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004510 return false;
4511 }
4512
4513 if (buffer->isMapped())
4514 {
Jamie Madill437fa652016-05-03 15:13:24 -04004515 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004516 return false;
4517 }
4518
4519 // Check for invalid bit combinations
4520 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4521 {
Jamie Madill437fa652016-05-03 15:13:24 -04004522 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004523 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4524 return false;
4525 }
4526
4527 GLbitfield writeOnlyBits =
4528 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4529
4530 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4531 {
Jamie Madill437fa652016-05-03 15:13:24 -04004532 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004533 "Invalid access bits when mapping buffer for reading: 0x%X.",
4534 access));
4535 return false;
4536 }
4537
4538 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4539 {
Jamie Madill437fa652016-05-03 15:13:24 -04004540 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004541 GL_INVALID_OPERATION,
4542 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4543 return false;
4544 }
4545 return true;
4546}
4547
4548bool ValidateFlushMappedBufferRangeBase(Context *context,
4549 GLenum target,
4550 GLintptr offset,
4551 GLsizeiptr length)
4552{
4553 if (offset < 0 || length < 0)
4554 {
Jamie Madill437fa652016-05-03 15:13:24 -04004555 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004556 return false;
4557 }
4558
4559 if (!ValidBufferTarget(context, target))
4560 {
Jamie Madill437fa652016-05-03 15:13:24 -04004561 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004562 return false;
4563 }
4564
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004565 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004566
4567 if (buffer == nullptr)
4568 {
Jamie Madill437fa652016-05-03 15:13:24 -04004569 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004570 return false;
4571 }
4572
4573 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4574 {
Jamie Madill437fa652016-05-03 15:13:24 -04004575 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004576 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4577 return false;
4578 }
4579
4580 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004581 CheckedNumeric<size_t> checkedOffset(offset);
4582 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004583
Jamie Madille2e406c2016-06-02 13:04:10 -04004584 if (!checkedSize.IsValid() ||
4585 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004586 {
Jamie Madill437fa652016-05-03 15:13:24 -04004587 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004588 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4589 return false;
4590 }
4591
4592 return true;
4593}
4594
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004595bool ValidateGenerateMipmap(Context *context, GLenum target)
4596{
4597 if (!ValidTextureTarget(context, target))
4598 {
4599 context->handleError(Error(GL_INVALID_ENUM));
4600 return false;
4601 }
4602
4603 Texture *texture = context->getTargetTexture(target);
4604
4605 if (texture == nullptr)
4606 {
4607 context->handleError(Error(GL_INVALID_OPERATION));
4608 return false;
4609 }
4610
4611 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4612
4613 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4614 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4615 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4616 {
4617 context->handleError(Error(GL_INVALID_OPERATION));
4618 return false;
4619 }
4620
Jamie Madilla3944d42016-07-22 22:13:26 -04004621 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4622 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4623 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004624
4625 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4626 // unsized formats or that are color renderable and filterable. Since we do not track if
4627 // the texture was created with sized or unsized format (only sized formats are stored),
4628 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4629 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4630 // textures since they're the only texture format that can be created with unsized formats
4631 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4632 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004633 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4634 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004635 {
4636 context->handleError(Error(GL_INVALID_OPERATION));
4637 return false;
4638 }
4639
4640 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004641 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004642 {
4643 context->handleError(Error(GL_INVALID_OPERATION));
4644 return false;
4645 }
4646
4647 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004648 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004649 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4650 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4651 {
Geoff Lang55482a12016-11-21 16:54:01 -05004652 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004653 context->handleError(Error(GL_INVALID_OPERATION));
4654 return false;
4655 }
4656
4657 // Cube completeness check
4658 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4659 {
4660 context->handleError(Error(GL_INVALID_OPERATION));
4661 return false;
4662 }
4663
4664 return true;
4665}
4666
Olli Etuaho41997e72016-03-10 13:38:39 +02004667bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4668{
4669 return ValidateGenOrDelete(context, n);
4670}
4671
4672bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4673{
4674 return ValidateGenOrDelete(context, n);
4675}
4676
4677bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4678{
4679 return ValidateGenOrDelete(context, n);
4680}
4681
4682bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4683{
4684 return ValidateGenOrDelete(context, n);
4685}
4686
4687bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4688{
4689 return ValidateGenOrDelete(context, n);
4690}
4691
4692bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4693{
4694 return ValidateGenOrDelete(context, n);
4695}
4696
4697bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4698{
4699 return ValidateGenOrDelete(context, n);
4700}
4701
4702bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4703{
4704 return ValidateGenOrDelete(context, n);
4705}
4706
4707bool ValidateGenOrDelete(Context *context, GLint n)
4708{
4709 if (n < 0)
4710 {
Jamie Madill437fa652016-05-03 15:13:24 -04004711 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004712 return false;
4713 }
4714 return true;
4715}
4716
Geoff Langf41a7152016-09-19 15:11:17 -04004717bool ValidateEnable(Context *context, GLenum cap)
4718{
4719 if (!ValidCap(context, cap, false))
4720 {
4721 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4722 return false;
4723 }
4724
4725 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4726 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4727 {
4728 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4729 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4730
4731 // We also output an error message to the debugger window if tracing is active, so that
4732 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05004733 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04004734 return false;
4735 }
4736
4737 return true;
4738}
4739
4740bool ValidateDisable(Context *context, GLenum cap)
4741{
4742 if (!ValidCap(context, cap, false))
4743 {
4744 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4745 return false;
4746 }
4747
4748 return true;
4749}
4750
4751bool ValidateIsEnabled(Context *context, GLenum cap)
4752{
4753 if (!ValidCap(context, cap, true))
4754 {
4755 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4756 return false;
4757 }
4758
4759 return true;
4760}
4761
Geoff Langff5b2d52016-09-07 11:32:23 -04004762bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4763{
4764 if (!context->getExtensions().robustClientMemory)
4765 {
4766 context->handleError(
4767 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4768 return false;
4769 }
4770
4771 if (bufSize < 0)
4772 {
4773 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4774 return false;
4775 }
4776
4777 return true;
4778}
4779
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004780bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4781{
4782 if (bufSize < numParams)
4783 {
4784 context->handleError(Error(GL_INVALID_OPERATION,
4785 "%u parameters are required but %i were provided.", numParams,
4786 bufSize));
4787 return false;
4788 }
4789
4790 return true;
4791}
4792
Geoff Langff5b2d52016-09-07 11:32:23 -04004793bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4794 GLenum target,
4795 GLenum attachment,
4796 GLenum pname,
4797 GLsizei *numParams)
4798{
4799 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4800 *numParams = 1;
4801
4802 if (!ValidFramebufferTarget(target))
4803 {
4804 context->handleError(Error(GL_INVALID_ENUM));
4805 return false;
4806 }
4807
4808 int clientVersion = context->getClientMajorVersion();
4809
4810 switch (pname)
4811 {
4812 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4813 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4814 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4815 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4816 break;
4817
4818 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4819 if (clientVersion < 3 && !context->getExtensions().sRGB)
4820 {
4821 context->handleError(Error(GL_INVALID_ENUM));
4822 return false;
4823 }
4824 break;
4825
4826 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4827 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4828 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4829 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4830 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4831 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4832 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4833 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4834 if (clientVersion < 3)
4835 {
4836 context->handleError(Error(GL_INVALID_ENUM));
4837 return false;
4838 }
4839 break;
4840
4841 default:
4842 context->handleError(Error(GL_INVALID_ENUM));
4843 return false;
4844 }
4845
4846 // Determine if the attachment is a valid enum
4847 switch (attachment)
4848 {
4849 case GL_BACK:
4850 case GL_FRONT:
4851 case GL_DEPTH:
4852 case GL_STENCIL:
4853 case GL_DEPTH_STENCIL_ATTACHMENT:
4854 if (clientVersion < 3)
4855 {
4856 context->handleError(Error(GL_INVALID_ENUM));
4857 return false;
4858 }
4859 break;
4860
4861 case GL_DEPTH_ATTACHMENT:
4862 case GL_STENCIL_ATTACHMENT:
4863 break;
4864
4865 default:
4866 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4867 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4868 {
4869 context->handleError(Error(GL_INVALID_ENUM));
4870 return false;
4871 }
4872 break;
4873 }
4874
4875 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4876 ASSERT(framebuffer);
4877
4878 if (framebuffer->id() == 0)
4879 {
4880 if (clientVersion < 3)
4881 {
4882 context->handleError(Error(GL_INVALID_OPERATION));
4883 return false;
4884 }
4885
4886 switch (attachment)
4887 {
4888 case GL_BACK:
4889 case GL_DEPTH:
4890 case GL_STENCIL:
4891 break;
4892
4893 default:
4894 context->handleError(Error(GL_INVALID_OPERATION));
4895 return false;
4896 }
4897 }
4898 else
4899 {
4900 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4901 {
4902 // Valid attachment query
4903 }
4904 else
4905 {
4906 switch (attachment)
4907 {
4908 case GL_DEPTH_ATTACHMENT:
4909 case GL_STENCIL_ATTACHMENT:
4910 break;
4911
4912 case GL_DEPTH_STENCIL_ATTACHMENT:
4913 if (!framebuffer->hasValidDepthStencil())
4914 {
4915 context->handleError(Error(GL_INVALID_OPERATION));
4916 return false;
4917 }
4918 break;
4919
4920 default:
4921 context->handleError(Error(GL_INVALID_OPERATION));
4922 return false;
4923 }
4924 }
4925 }
4926
4927 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4928 if (attachmentObject)
4929 {
4930 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4931 attachmentObject->type() == GL_TEXTURE ||
4932 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4933
4934 switch (pname)
4935 {
4936 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4937 if (attachmentObject->type() != GL_RENDERBUFFER &&
4938 attachmentObject->type() != GL_TEXTURE)
4939 {
4940 context->handleError(Error(GL_INVALID_ENUM));
4941 return false;
4942 }
4943 break;
4944
4945 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4946 if (attachmentObject->type() != GL_TEXTURE)
4947 {
4948 context->handleError(Error(GL_INVALID_ENUM));
4949 return false;
4950 }
4951 break;
4952
4953 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4954 if (attachmentObject->type() != GL_TEXTURE)
4955 {
4956 context->handleError(Error(GL_INVALID_ENUM));
4957 return false;
4958 }
4959 break;
4960
4961 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4962 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4963 {
4964 context->handleError(Error(GL_INVALID_OPERATION));
4965 return false;
4966 }
4967 break;
4968
4969 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4970 if (attachmentObject->type() != GL_TEXTURE)
4971 {
4972 context->handleError(Error(GL_INVALID_ENUM));
4973 return false;
4974 }
4975 break;
4976
4977 default:
4978 break;
4979 }
4980 }
4981 else
4982 {
4983 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4984 // is NONE, then querying any other pname will generate INVALID_ENUM.
4985
4986 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4987 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4988 // INVALID_OPERATION for all other pnames
4989
4990 switch (pname)
4991 {
4992 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4993 break;
4994
4995 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4996 if (clientVersion < 3)
4997 {
4998 context->handleError(Error(GL_INVALID_ENUM));
4999 return false;
5000 }
5001 break;
5002
5003 default:
5004 if (clientVersion < 3)
5005 {
5006 context->handleError(Error(GL_INVALID_ENUM));
5007 return false;
5008 }
5009 else
5010 {
5011 context->handleError(Error(GL_INVALID_OPERATION));
5012 return false;
5013 }
5014 }
5015 }
5016
5017 return true;
5018}
5019
5020bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5021 GLenum target,
5022 GLenum attachment,
5023 GLenum pname,
5024 GLsizei bufSize,
5025 GLsizei *numParams)
5026{
5027 if (!ValidateRobustEntryPoint(context, bufSize))
5028 {
5029 return false;
5030 }
5031
5032 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5033 {
5034 return false;
5035 }
5036
5037 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5038 {
5039 return false;
5040 }
5041
5042 return true;
5043}
5044
5045bool ValidateGetBufferParameteriv(ValidationContext *context,
5046 GLenum target,
5047 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005048 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005049{
Geoff Langebebe1c2016-10-14 12:01:31 -04005050 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005051}
5052
5053bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5054 GLenum target,
5055 GLenum pname,
5056 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005057 GLsizei *length,
5058 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005059{
5060 if (!ValidateRobustEntryPoint(context, bufSize))
5061 {
5062 return false;
5063 }
5064
Geoff Langebebe1c2016-10-14 12:01:31 -04005065 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005066 {
5067 return false;
5068 }
5069
Geoff Langebebe1c2016-10-14 12:01:31 -04005070 if (!ValidateRobustBufferSize(context, bufSize, *length))
5071 {
5072 return false;
5073 }
5074
5075 return true;
5076}
5077
5078bool ValidateGetBufferParameteri64v(ValidationContext *context,
5079 GLenum target,
5080 GLenum pname,
5081 GLint64 *params)
5082{
5083 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5084}
5085
5086bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5087 GLenum target,
5088 GLenum pname,
5089 GLsizei bufSize,
5090 GLsizei *length,
5091 GLint64 *params)
5092{
5093 if (!ValidateRobustEntryPoint(context, bufSize))
5094 {
5095 return false;
5096 }
5097
5098 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5099 {
5100 return false;
5101 }
5102
5103 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005104 {
5105 return false;
5106 }
5107
5108 return true;
5109}
5110
5111bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5112{
5113 // Currently, all GetProgramiv queries return 1 parameter
5114 *numParams = 1;
5115
5116 Program *programObject = GetValidProgram(context, program);
5117 if (!programObject)
5118 {
5119 return false;
5120 }
5121
5122 switch (pname)
5123 {
5124 case GL_DELETE_STATUS:
5125 case GL_LINK_STATUS:
5126 case GL_VALIDATE_STATUS:
5127 case GL_INFO_LOG_LENGTH:
5128 case GL_ATTACHED_SHADERS:
5129 case GL_ACTIVE_ATTRIBUTES:
5130 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5131 case GL_ACTIVE_UNIFORMS:
5132 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5133 break;
5134
5135 case GL_PROGRAM_BINARY_LENGTH:
5136 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5137 {
5138 context->handleError(Error(GL_INVALID_ENUM,
5139 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5140 "GL_OES_get_program_binary or ES 3.0."));
5141 return false;
5142 }
5143 break;
5144
5145 case GL_ACTIVE_UNIFORM_BLOCKS:
5146 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5147 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5148 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5149 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5150 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5151 if (context->getClientMajorVersion() < 3)
5152 {
5153 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5154 return false;
5155 }
5156 break;
5157
5158 default:
5159 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5160 return false;
5161 }
5162
5163 return true;
5164}
5165
5166bool ValidateGetProgramivRobustANGLE(Context *context,
5167 GLuint program,
5168 GLenum pname,
5169 GLsizei bufSize,
5170 GLsizei *numParams)
5171{
5172 if (!ValidateRobustEntryPoint(context, bufSize))
5173 {
5174 return false;
5175 }
5176
5177 if (!ValidateGetProgramiv(context, program, pname, numParams))
5178 {
5179 return false;
5180 }
5181
5182 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5183 {
5184 return false;
5185 }
5186
5187 return true;
5188}
5189
Geoff Lang740d9022016-10-07 11:20:52 -04005190bool ValidateGetRenderbufferParameteriv(Context *context,
5191 GLenum target,
5192 GLenum pname,
5193 GLint *params)
5194{
5195 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5196}
5197
5198bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5199 GLenum target,
5200 GLenum pname,
5201 GLsizei bufSize,
5202 GLsizei *length,
5203 GLint *params)
5204{
5205 if (!ValidateRobustEntryPoint(context, bufSize))
5206 {
5207 return false;
5208 }
5209
5210 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5211 {
5212 return false;
5213 }
5214
5215 if (!ValidateRobustBufferSize(context, bufSize, *length))
5216 {
5217 return false;
5218 }
5219
5220 return true;
5221}
5222
Geoff Langd7d0ed32016-10-07 11:33:51 -04005223bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5224{
5225 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5226}
5227
5228bool ValidateGetShaderivRobustANGLE(Context *context,
5229 GLuint shader,
5230 GLenum pname,
5231 GLsizei bufSize,
5232 GLsizei *length,
5233 GLint *params)
5234{
5235 if (!ValidateRobustEntryPoint(context, bufSize))
5236 {
5237 return false;
5238 }
5239
5240 if (!ValidateGetShaderivBase(context, shader, pname, length))
5241 {
5242 return false;
5243 }
5244
5245 if (!ValidateRobustBufferSize(context, bufSize, *length))
5246 {
5247 return false;
5248 }
5249
5250 return true;
5251}
5252
Geoff Langc1984ed2016-10-07 12:41:00 -04005253bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5254{
5255 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5256}
5257
5258bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5259 GLenum target,
5260 GLenum pname,
5261 GLsizei bufSize,
5262 GLsizei *length,
5263 GLfloat *params)
5264{
5265 if (!ValidateRobustEntryPoint(context, bufSize))
5266 {
5267 return false;
5268 }
5269
5270 if (!ValidateGetTexParameterBase(context, target, pname, length))
5271 {
5272 return false;
5273 }
5274
5275 if (!ValidateRobustBufferSize(context, bufSize, *length))
5276 {
5277 return false;
5278 }
5279
5280 return true;
5281}
5282
5283bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5284{
5285 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5286}
5287
5288bool ValidateGetTexParameterivRobustANGLE(Context *context,
5289 GLenum target,
5290 GLenum pname,
5291 GLsizei bufSize,
5292 GLsizei *length,
5293 GLint *params)
5294{
5295 if (!ValidateRobustEntryPoint(context, bufSize))
5296 {
5297 return false;
5298 }
5299
5300 if (!ValidateGetTexParameterBase(context, target, pname, length))
5301 {
5302 return false;
5303 }
5304
5305 if (!ValidateRobustBufferSize(context, bufSize, *length))
5306 {
5307 return false;
5308 }
5309
5310 return true;
5311}
5312
5313bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5314{
5315 return ValidateTexParameterBase(context, target, pname, -1, &param);
5316}
5317
5318bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5319{
5320 return ValidateTexParameterBase(context, target, pname, -1, params);
5321}
5322
5323bool ValidateTexParameterfvRobustANGLE(Context *context,
5324 GLenum target,
5325 GLenum pname,
5326 GLsizei bufSize,
5327 const GLfloat *params)
5328{
5329 if (!ValidateRobustEntryPoint(context, bufSize))
5330 {
5331 return false;
5332 }
5333
5334 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5335}
5336
5337bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5338{
5339 return ValidateTexParameterBase(context, target, pname, -1, &param);
5340}
5341
5342bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5343{
5344 return ValidateTexParameterBase(context, target, pname, -1, params);
5345}
5346
5347bool ValidateTexParameterivRobustANGLE(Context *context,
5348 GLenum target,
5349 GLenum pname,
5350 GLsizei bufSize,
5351 const GLint *params)
5352{
5353 if (!ValidateRobustEntryPoint(context, bufSize))
5354 {
5355 return false;
5356 }
5357
5358 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5359}
5360
5361bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5362{
5363 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5364}
5365
5366bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5367 GLuint sampler,
5368 GLenum pname,
5369 GLuint bufSize,
5370 GLsizei *length,
5371 GLfloat *params)
5372{
5373 if (!ValidateRobustEntryPoint(context, bufSize))
5374 {
5375 return false;
5376 }
5377
5378 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5379 {
5380 return false;
5381 }
5382
5383 if (!ValidateRobustBufferSize(context, bufSize, *length))
5384 {
5385 return false;
5386 }
5387
5388 return true;
5389}
5390
5391bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5392{
5393 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5394}
5395
5396bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5397 GLuint sampler,
5398 GLenum pname,
5399 GLuint bufSize,
5400 GLsizei *length,
5401 GLint *params)
5402{
5403 if (!ValidateRobustEntryPoint(context, bufSize))
5404 {
5405 return false;
5406 }
5407
5408 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5409 {
5410 return false;
5411 }
5412
5413 if (!ValidateRobustBufferSize(context, bufSize, *length))
5414 {
5415 return false;
5416 }
5417
5418 return true;
5419}
5420
5421bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5422{
5423 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5424}
5425
5426bool ValidateSamplerParameterfv(Context *context,
5427 GLuint sampler,
5428 GLenum pname,
5429 const GLfloat *params)
5430{
5431 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5432}
5433
5434bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5435 GLuint sampler,
5436 GLenum pname,
5437 GLsizei bufSize,
5438 const GLfloat *params)
5439{
5440 if (!ValidateRobustEntryPoint(context, bufSize))
5441 {
5442 return false;
5443 }
5444
5445 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5446}
5447
5448bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5449{
5450 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5451}
5452
5453bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5454{
5455 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5456}
5457
5458bool ValidateSamplerParameterivRobustANGLE(Context *context,
5459 GLuint sampler,
5460 GLenum pname,
5461 GLsizei bufSize,
5462 const GLint *params)
5463{
5464 if (!ValidateRobustEntryPoint(context, bufSize))
5465 {
5466 return false;
5467 }
5468
5469 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5470}
5471
Geoff Lang0b031062016-10-13 14:30:04 -04005472bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5473{
5474 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5475}
5476
5477bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5478 GLuint index,
5479 GLenum pname,
5480 GLsizei bufSize,
5481 GLsizei *length,
5482 GLfloat *params)
5483{
5484 if (!ValidateRobustEntryPoint(context, bufSize))
5485 {
5486 return false;
5487 }
5488
5489 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5490 {
5491 return false;
5492 }
5493
5494 if (!ValidateRobustBufferSize(context, bufSize, *length))
5495 {
5496 return false;
5497 }
5498
5499 return true;
5500}
5501
5502bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5503{
5504 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5505}
5506
5507bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5508 GLuint index,
5509 GLenum pname,
5510 GLsizei bufSize,
5511 GLsizei *length,
5512 GLint *params)
5513{
5514 if (!ValidateRobustEntryPoint(context, bufSize))
5515 {
5516 return false;
5517 }
5518
5519 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5520 {
5521 return false;
5522 }
5523
5524 if (!ValidateRobustBufferSize(context, bufSize, *length))
5525 {
5526 return false;
5527 }
5528
5529 return true;
5530}
5531
5532bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5533{
5534 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5535}
5536
5537bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5538 GLuint index,
5539 GLenum pname,
5540 GLsizei bufSize,
5541 GLsizei *length,
5542 void **pointer)
5543{
5544 if (!ValidateRobustEntryPoint(context, bufSize))
5545 {
5546 return false;
5547 }
5548
5549 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5550 {
5551 return false;
5552 }
5553
5554 if (!ValidateRobustBufferSize(context, bufSize, *length))
5555 {
5556 return false;
5557 }
5558
5559 return true;
5560}
5561
5562bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5563{
5564 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5565}
5566
5567bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5568 GLuint index,
5569 GLenum pname,
5570 GLsizei bufSize,
5571 GLsizei *length,
5572 GLint *params)
5573{
5574 if (!ValidateRobustEntryPoint(context, bufSize))
5575 {
5576 return false;
5577 }
5578
5579 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5580 {
5581 return false;
5582 }
5583
5584 if (!ValidateRobustBufferSize(context, bufSize, *length))
5585 {
5586 return false;
5587 }
5588
5589 return true;
5590}
5591
5592bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5593{
5594 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5595}
5596
5597bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5598 GLuint index,
5599 GLenum pname,
5600 GLsizei bufSize,
5601 GLsizei *length,
5602 GLuint *params)
5603{
5604 if (!ValidateRobustEntryPoint(context, bufSize))
5605 {
5606 return false;
5607 }
5608
5609 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5610 {
5611 return false;
5612 }
5613
5614 if (!ValidateRobustBufferSize(context, bufSize, *length))
5615 {
5616 return false;
5617 }
5618
5619 return true;
5620}
5621
Geoff Lang6899b872016-10-14 11:30:13 -04005622bool ValidateGetActiveUniformBlockiv(Context *context,
5623 GLuint program,
5624 GLuint uniformBlockIndex,
5625 GLenum pname,
5626 GLint *params)
5627{
5628 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5629}
5630
5631bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5632 GLuint program,
5633 GLuint uniformBlockIndex,
5634 GLenum pname,
5635 GLsizei bufSize,
5636 GLsizei *length,
5637 GLint *params)
5638{
5639 if (!ValidateRobustEntryPoint(context, bufSize))
5640 {
5641 return false;
5642 }
5643
5644 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5645 {
5646 return false;
5647 }
5648
5649 if (!ValidateRobustBufferSize(context, bufSize, *length))
5650 {
5651 return false;
5652 }
5653
5654 return true;
5655}
5656
Geoff Lang0a9661f2016-10-20 10:59:20 -07005657bool ValidateGetInternalFormativ(Context *context,
5658 GLenum target,
5659 GLenum internalformat,
5660 GLenum pname,
5661 GLsizei bufSize,
5662 GLint *params)
5663{
5664 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5665 nullptr);
5666}
5667
5668bool ValidateGetInternalFormativRobustANGLE(Context *context,
5669 GLenum target,
5670 GLenum internalformat,
5671 GLenum pname,
5672 GLsizei bufSize,
5673 GLsizei *length,
5674 GLint *params)
5675{
5676 if (!ValidateRobustEntryPoint(context, bufSize))
5677 {
5678 return false;
5679 }
5680
5681 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5682 {
5683 return false;
5684 }
5685
5686 if (!ValidateRobustBufferSize(context, bufSize, *length))
5687 {
5688 return false;
5689 }
5690
5691 return true;
5692}
5693
Jamie Madillc29968b2016-01-20 11:17:23 -05005694} // namespace gl