blob: be6c72a81e987436ae72e31da1d2a60dbc45d747 [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();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080049 const auto &vertexBindings = vao->getVertexBindings();
He Yunchaoced53ae2016-11-29 15:00:51 +080050 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040051 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
52 {
53 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallezfd456442016-12-21 17:57:00 -050054 if (!program->isAttribLocationActive(attributeIndex) || !attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040055 {
Corentin Wallezfd456442016-12-21 17:57:00 -050056 continue;
57 }
Jamie Madill1ca74672015-07-21 15:14:11 -040058
Jiawei-Shao2597fb62016-12-09 16:38:02 +080059 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
Corentin Wallezfd456442016-12-21 17:57:00 -050060 // If we have no buffer, then we either get an error, or there are no more checks to be done.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080061 gl::Buffer *buffer = binding.buffer.get();
Corentin Wallezfd456442016-12-21 17:57:00 -050062 if (!buffer)
63 {
Geoff Langfeb8c682017-02-13 16:07:35 -050064 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050065 {
66 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050067 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
68 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
69 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
70 // error.
Corentin Wallez327411e2016-12-09 11:09:17 -050071 context->handleError(
72 Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer."));
Corentin Wallezfd456442016-12-21 17:57:00 -050073 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050074 }
Corentin Wallezfd456442016-12-21 17:57:00 -050075 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040076 {
77 // This is an application error that would normally result in a crash,
78 // but we catch it and return an error
Corentin Wallezfd456442016-12-21 17:57:00 -050079 context->handleError(
80 Error(GL_INVALID_OPERATION,
81 "An enabled vertex array has no buffer and no pointer."));
Jamie Madill1ca74672015-07-21 15:14:11 -040082 return false;
83 }
Corentin Wallezfd456442016-12-21 17:57:00 -050084 continue;
85 }
86
87 // If we're drawing zero vertices, we have enough data.
88 if (vertexCount <= 0 || primcount <= 0)
89 {
90 continue;
91 }
92
93 GLint maxVertexElement = 0;
Jiawei-Shao2597fb62016-12-09 16:38:02 +080094 if (binding.divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -050095 {
96 maxVertexElement = maxVertex;
97 }
98 else
99 {
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800100 maxVertexElement = (primcount - 1) / binding.divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500101 }
102
103 // We do manual overflow checks here instead of using safe_math.h because it was
104 // a bottleneck. Thanks to some properties of GL we know inequalities that can
105 // help us make the overflow checks faster.
106
107 // The max possible attribSize is 16 for a vector of 4 32 bit values.
108 constexpr uint64_t kMaxAttribSize = 16;
109 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
110 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
111
112 // We know attribStride is given as a GLsizei which is typedefed to int.
113 // We also know an upper bound for attribSize.
114 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800115 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500116 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
117 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
118
119 // Computing the max offset using uint64_t without attrib.offset is overflow
120 // safe. Note: Last vertex element does not take the full stride!
121 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
122 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
123
124 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800125 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
126 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500127 {
128 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
129 return false;
130 }
131 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
132
133 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
134 // We can return INVALID_OPERATION if our vertex attribute does not have
135 // enough backing data.
136 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
137 {
138 context->handleError(Error(GL_INVALID_OPERATION,
139 "Vertex buffer is not big enough for the draw call"));
140 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400141 }
142 }
143
144 return true;
145}
146
Geoff Langf607c602016-09-21 11:46:48 -0400147bool ValidReadPixelsFormatType(ValidationContext *context,
148 GLenum framebufferComponentType,
149 GLenum format,
150 GLenum type)
151{
152 switch (framebufferComponentType)
153 {
154 case GL_UNSIGNED_NORMALIZED:
155 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
156 // ReadPixels with BGRA even if the extension is not present
157 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
158 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
159 type == GL_UNSIGNED_BYTE);
160
161 case GL_SIGNED_NORMALIZED:
162 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
163
164 case GL_INT:
165 return (format == GL_RGBA_INTEGER && type == GL_INT);
166
167 case GL_UNSIGNED_INT:
168 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
169
170 case GL_FLOAT:
171 return (format == GL_RGBA && type == GL_FLOAT);
172
173 default:
174 UNREACHABLE();
175 return false;
176 }
177}
178
Geoff Langf41a7152016-09-19 15:11:17 -0400179bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500180{
181 switch (cap)
182 {
Geoff Langf41a7152016-09-19 15:11:17 -0400183 // EXT_multisample_compatibility
184 case GL_MULTISAMPLE_EXT:
185 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
186 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300187
Geoff Langf41a7152016-09-19 15:11:17 -0400188 case GL_CULL_FACE:
189 case GL_POLYGON_OFFSET_FILL:
190 case GL_SAMPLE_ALPHA_TO_COVERAGE:
191 case GL_SAMPLE_COVERAGE:
192 case GL_SCISSOR_TEST:
193 case GL_STENCIL_TEST:
194 case GL_DEPTH_TEST:
195 case GL_BLEND:
196 case GL_DITHER:
197 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500198
Geoff Langf41a7152016-09-19 15:11:17 -0400199 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
200 case GL_RASTERIZER_DISCARD:
201 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500202
Geoff Langf41a7152016-09-19 15:11:17 -0400203 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
204 case GL_DEBUG_OUTPUT:
205 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500206
Geoff Langf41a7152016-09-19 15:11:17 -0400207 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
208 return queryOnly && context->getExtensions().bindGeneratesResource;
209
Geoff Langfeb8c682017-02-13 16:07:35 -0500210 case GL_CLIENT_ARRAYS_ANGLE:
211 return queryOnly && context->getExtensions().clientArrays;
212
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700213 case GL_FRAMEBUFFER_SRGB_EXT:
214 return context->getExtensions().sRGBWriteControl;
215
Geoff Lang3b573612016-10-31 14:08:10 -0400216 case GL_SAMPLE_MASK:
Geoff Lang3b573612016-10-31 14:08:10 -0400217 return context->getClientVersion() >= Version(3, 1);
218
Jamie Madille08a1d32017-03-07 17:24:06 -0500219 case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
220 return queryOnly && context->getExtensions().robustResourceInitialization;
221
Geoff Langf41a7152016-09-19 15:11:17 -0400222 default:
223 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500224 }
225}
226
Geoff Lang62fce5b2016-09-30 10:46:35 -0400227bool ValidateReadPixelsBase(ValidationContext *context,
228 GLint x,
229 GLint y,
230 GLsizei width,
231 GLsizei height,
232 GLenum format,
233 GLenum type,
234 GLsizei bufSize,
235 GLsizei *length,
236 GLvoid *pixels)
237{
238 if (length != nullptr)
239 {
240 *length = 0;
241 }
242
243 if (width < 0 || height < 0)
244 {
245 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
246 return false;
247 }
248
249 auto readFramebuffer = context->getGLState().getReadFramebuffer();
250
251 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
252 {
253 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
254 return false;
255 }
256
257 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
258 {
259 context->handleError(Error(GL_INVALID_OPERATION));
260 return false;
261 }
262
263 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
264 ASSERT(framebuffer);
265
266 if (framebuffer->getReadBufferState() == GL_NONE)
267 {
268 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
269 return false;
270 }
271
272 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500273 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
274 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
275 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
276 // situation is an application error that would lead to a crash in ANGLE.
277 if (readBuffer == nullptr)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400278 {
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500279 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
Geoff Lang62fce5b2016-09-30 10:46:35 -0400280 return false;
281 }
282
283 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
284 GLenum currentType = framebuffer->getImplementationColorReadType();
285 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
286
287 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
288 bool validFormatTypeCombination =
289 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
290
291 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
292 {
293 context->handleError(Error(GL_INVALID_OPERATION));
294 return false;
295 }
296
297 // Check for pixel pack buffer related API errors
298 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
299 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
300 {
301 // ...the buffer object's data store is currently mapped.
302 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
303 return false;
304 }
305
306 // .. the data would be packed to the buffer object such that the memory writes required
307 // would exceed the data store size.
308 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
309 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
310 const gl::Extents size(width, height, 1);
311 const auto &pack = context->getGLState().getPackState();
312
313 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
314 if (endByteOrErr.isError())
315 {
316 context->handleError(endByteOrErr.getError());
317 return false;
318 }
319
320 size_t endByte = endByteOrErr.getResult();
321 if (bufSize >= 0)
322 {
323
324 if (static_cast<size_t>(bufSize) < endByte)
325 {
326 context->handleError(
327 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
328 return false;
329 }
330 }
331
332 if (pixelPackBuffer != nullptr)
333 {
334 CheckedNumeric<size_t> checkedEndByte(endByte);
335 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
336 checkedEndByte += checkedOffset;
337
338 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
339 {
340 // Overflow past the end of the buffer
341 context->handleError(
342 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
343 return false;
344 }
345 }
346
347 if (length != nullptr)
348 {
349 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
350 {
351 context->handleError(
352 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
353 return false;
354 }
355
356 *length = static_cast<GLsizei>(endByte);
357 }
358
359 return true;
360}
361
Geoff Lang740d9022016-10-07 11:20:52 -0400362bool ValidateGetRenderbufferParameterivBase(Context *context,
363 GLenum target,
364 GLenum pname,
365 GLsizei *length)
366{
367 if (length)
368 {
369 *length = 0;
370 }
371
372 if (target != GL_RENDERBUFFER)
373 {
374 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
375 return false;
376 }
377
378 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
379 if (renderbuffer == nullptr)
380 {
381 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
382 return false;
383 }
384
385 switch (pname)
386 {
387 case GL_RENDERBUFFER_WIDTH:
388 case GL_RENDERBUFFER_HEIGHT:
389 case GL_RENDERBUFFER_INTERNAL_FORMAT:
390 case GL_RENDERBUFFER_RED_SIZE:
391 case GL_RENDERBUFFER_GREEN_SIZE:
392 case GL_RENDERBUFFER_BLUE_SIZE:
393 case GL_RENDERBUFFER_ALPHA_SIZE:
394 case GL_RENDERBUFFER_DEPTH_SIZE:
395 case GL_RENDERBUFFER_STENCIL_SIZE:
396 break;
397
398 case GL_RENDERBUFFER_SAMPLES_ANGLE:
399 if (!context->getExtensions().framebufferMultisample)
400 {
401 context->handleError(
402 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
403 return false;
404 }
405 break;
406
407 default:
408 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
409 return false;
410 }
411
412 if (length)
413 {
414 *length = 1;
415 }
416 return true;
417}
418
Geoff Langd7d0ed32016-10-07 11:33:51 -0400419bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
420{
421 if (length)
422 {
423 *length = 0;
424 }
425
426 if (GetValidShader(context, shader) == nullptr)
427 {
428 return false;
429 }
430
431 switch (pname)
432 {
433 case GL_SHADER_TYPE:
434 case GL_DELETE_STATUS:
435 case GL_COMPILE_STATUS:
436 case GL_INFO_LOG_LENGTH:
437 case GL_SHADER_SOURCE_LENGTH:
438 break;
439
440 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
441 if (!context->getExtensions().translatedShaderSource)
442 {
443 context->handleError(
444 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
445 return false;
446 }
447 break;
448
449 default:
450 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
451 return false;
452 }
453
454 if (length)
455 {
456 *length = 1;
457 }
458 return true;
459}
460
Geoff Langc1984ed2016-10-07 12:41:00 -0400461bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
462{
463 if (length)
464 {
465 *length = 0;
466 }
467
468 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
469 {
470 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
471 return false;
472 }
473
474 if (context->getTargetTexture(target) == nullptr)
475 {
476 // Should only be possible for external textures
477 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
478 return false;
479 }
480
481 switch (pname)
482 {
483 case GL_TEXTURE_MAG_FILTER:
484 case GL_TEXTURE_MIN_FILTER:
485 case GL_TEXTURE_WRAP_S:
486 case GL_TEXTURE_WRAP_T:
487 break;
488
489 case GL_TEXTURE_USAGE_ANGLE:
490 if (!context->getExtensions().textureUsage)
491 {
492 context->handleError(
493 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
494 return false;
495 }
496 break;
497
498 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
499 if (!context->getExtensions().textureFilterAnisotropic)
500 {
501 context->handleError(
502 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
503 return false;
504 }
505 break;
506
507 case GL_TEXTURE_IMMUTABLE_FORMAT:
508 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
509 {
510 context->handleError(
511 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
512 return false;
513 }
514 break;
515
516 case GL_TEXTURE_WRAP_R:
517 case GL_TEXTURE_IMMUTABLE_LEVELS:
518 case GL_TEXTURE_SWIZZLE_R:
519 case GL_TEXTURE_SWIZZLE_G:
520 case GL_TEXTURE_SWIZZLE_B:
521 case GL_TEXTURE_SWIZZLE_A:
522 case GL_TEXTURE_BASE_LEVEL:
523 case GL_TEXTURE_MAX_LEVEL:
524 case GL_TEXTURE_MIN_LOD:
525 case GL_TEXTURE_MAX_LOD:
526 case GL_TEXTURE_COMPARE_MODE:
527 case GL_TEXTURE_COMPARE_FUNC:
528 if (context->getClientMajorVersion() < 3)
529 {
530 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
531 return false;
532 }
533 break;
534
Geoff Lang81c6b572016-10-19 14:07:52 -0700535 case GL_TEXTURE_SRGB_DECODE_EXT:
536 if (!context->getExtensions().textureSRGBDecode)
537 {
538 context->handleError(
539 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
540 return false;
541 }
542 break;
543
Geoff Langc1984ed2016-10-07 12:41:00 -0400544 default:
545 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
546 return false;
547 }
548
549 if (length)
550 {
551 *length = 1;
552 }
553 return true;
554}
555
556template <typename ParamType>
557bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
558{
559 switch (ConvertToGLenum(params[0]))
560 {
561 case GL_CLAMP_TO_EDGE:
562 break;
563
564 case GL_REPEAT:
565 case GL_MIRRORED_REPEAT:
566 if (isExternalTextureTarget)
567 {
568 // OES_EGL_image_external specifies this error.
569 context->handleError(Error(
570 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
571 return false;
572 }
573 break;
574
575 default:
576 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
577 return false;
578 }
579
580 return true;
581}
582
583template <typename ParamType>
584bool ValidateTextureMinFilterValue(Context *context,
585 ParamType *params,
586 bool isExternalTextureTarget)
587{
588 switch (ConvertToGLenum(params[0]))
589 {
590 case GL_NEAREST:
591 case GL_LINEAR:
592 break;
593
594 case GL_NEAREST_MIPMAP_NEAREST:
595 case GL_LINEAR_MIPMAP_NEAREST:
596 case GL_NEAREST_MIPMAP_LINEAR:
597 case GL_LINEAR_MIPMAP_LINEAR:
598 if (isExternalTextureTarget)
599 {
600 // OES_EGL_image_external specifies this error.
601 context->handleError(
602 Error(GL_INVALID_ENUM,
603 "external textures only support NEAREST and LINEAR filtering"));
604 return false;
605 }
606 break;
607
608 default:
609 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
610 return false;
611 }
612
613 return true;
614}
615
616template <typename ParamType>
617bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
618{
619 switch (ConvertToGLenum(params[0]))
620 {
621 case GL_NEAREST:
622 case GL_LINEAR:
623 break;
624
625 default:
626 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
627 return false;
628 }
629
630 return true;
631}
632
633template <typename ParamType>
634bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
635{
636 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
637 switch (ConvertToGLenum(params[0]))
638 {
639 case GL_NONE:
640 case GL_COMPARE_REF_TO_TEXTURE:
641 break;
642
643 default:
644 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
645 return false;
646 }
647
648 return true;
649}
650
651template <typename ParamType>
652bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
653{
654 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
655 switch (ConvertToGLenum(params[0]))
656 {
657 case GL_LEQUAL:
658 case GL_GEQUAL:
659 case GL_LESS:
660 case GL_GREATER:
661 case GL_EQUAL:
662 case GL_NOTEQUAL:
663 case GL_ALWAYS:
664 case GL_NEVER:
665 break;
666
667 default:
668 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
669 return false;
670 }
671
672 return true;
673}
674
675template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700676bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
677{
678 if (!context->getExtensions().textureSRGBDecode)
679 {
680 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
681 return false;
682 }
683
684 switch (ConvertToGLenum(params[0]))
685 {
686 case GL_DECODE_EXT:
687 case GL_SKIP_DECODE_EXT:
688 break;
689
690 default:
691 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
692 return false;
693 }
694
695 return true;
696}
697
698template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400699bool ValidateTexParameterBase(Context *context,
700 GLenum target,
701 GLenum pname,
702 GLsizei bufSize,
703 ParamType *params)
704{
705 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
706 {
707 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
708 return false;
709 }
710
711 if (context->getTargetTexture(target) == nullptr)
712 {
713 // Should only be possible for external textures
714 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
715 return false;
716 }
717
718 const GLsizei minBufSize = 1;
719 if (bufSize >= 0 && bufSize < minBufSize)
720 {
721 context->handleError(
722 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
723 return false;
724 }
725
726 switch (pname)
727 {
728 case GL_TEXTURE_WRAP_R:
729 case GL_TEXTURE_SWIZZLE_R:
730 case GL_TEXTURE_SWIZZLE_G:
731 case GL_TEXTURE_SWIZZLE_B:
732 case GL_TEXTURE_SWIZZLE_A:
733 case GL_TEXTURE_BASE_LEVEL:
734 case GL_TEXTURE_MAX_LEVEL:
735 case GL_TEXTURE_COMPARE_MODE:
736 case GL_TEXTURE_COMPARE_FUNC:
737 case GL_TEXTURE_MIN_LOD:
738 case GL_TEXTURE_MAX_LOD:
739 if (context->getClientMajorVersion() < 3)
740 {
741 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
742 return false;
743 }
744 if (target == GL_TEXTURE_EXTERNAL_OES &&
745 !context->getExtensions().eglImageExternalEssl3)
746 {
747 context->handleError(Error(GL_INVALID_ENUM,
748 "ES3 texture parameters are not available without "
749 "GL_OES_EGL_image_external_essl3."));
750 return false;
751 }
752 break;
753
754 default:
755 break;
756 }
757
758 switch (pname)
759 {
760 case GL_TEXTURE_WRAP_S:
761 case GL_TEXTURE_WRAP_T:
762 case GL_TEXTURE_WRAP_R:
763 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
764 {
765 return false;
766 }
767 break;
768
769 case GL_TEXTURE_MIN_FILTER:
770 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
771 {
772 return false;
773 }
774 break;
775
776 case GL_TEXTURE_MAG_FILTER:
777 if (!ValidateTextureMagFilterValue(context, params))
778 {
779 return false;
780 }
781 break;
782
783 case GL_TEXTURE_USAGE_ANGLE:
784 switch (ConvertToGLenum(params[0]))
785 {
786 case GL_NONE:
787 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
788 break;
789
790 default:
791 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
792 return false;
793 }
794 break;
795
796 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
797 if (!context->getExtensions().textureFilterAnisotropic)
798 {
799 context->handleError(
800 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
801 return false;
802 }
803
804 // we assume the parameter passed to this validation method is truncated, not rounded
805 if (params[0] < 1)
806 {
807 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
808 return false;
809 }
810 break;
811
812 case GL_TEXTURE_MIN_LOD:
813 case GL_TEXTURE_MAX_LOD:
814 // any value is permissible
815 break;
816
817 case GL_TEXTURE_COMPARE_MODE:
818 if (!ValidateTextureCompareModeValue(context, params))
819 {
820 return false;
821 }
822 break;
823
824 case GL_TEXTURE_COMPARE_FUNC:
825 if (!ValidateTextureCompareFuncValue(context, params))
826 {
827 return false;
828 }
829 break;
830
831 case GL_TEXTURE_SWIZZLE_R:
832 case GL_TEXTURE_SWIZZLE_G:
833 case GL_TEXTURE_SWIZZLE_B:
834 case GL_TEXTURE_SWIZZLE_A:
835 switch (ConvertToGLenum(params[0]))
836 {
837 case GL_RED:
838 case GL_GREEN:
839 case GL_BLUE:
840 case GL_ALPHA:
841 case GL_ZERO:
842 case GL_ONE:
843 break;
844
845 default:
846 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
847 return false;
848 }
849 break;
850
851 case GL_TEXTURE_BASE_LEVEL:
852 if (params[0] < 0)
853 {
854 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
855 return false;
856 }
857 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
858 {
859 context->handleError(
860 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
861 return false;
862 }
863 break;
864
865 case GL_TEXTURE_MAX_LEVEL:
866 if (params[0] < 0)
867 {
868 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
869 return false;
870 }
871 break;
872
Geoff Lang3b573612016-10-31 14:08:10 -0400873 case GL_DEPTH_STENCIL_TEXTURE_MODE:
874 if (context->getClientVersion() < Version(3, 1))
875 {
876 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
877 return false;
878 }
Geoff Lang9f090372016-12-02 10:20:43 -0500879 switch (ConvertToGLenum(params[0]))
880 {
881 case GL_DEPTH_COMPONENT:
882 case GL_STENCIL_INDEX:
883 break;
884
885 default:
886 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
887 return false;
888 }
Geoff Lang3b573612016-10-31 14:08:10 -0400889 break;
890
Geoff Lang81c6b572016-10-19 14:07:52 -0700891 case GL_TEXTURE_SRGB_DECODE_EXT:
892 if (!ValidateTextureSRGBDecodeValue(context, params))
893 {
894 return false;
895 }
896 break;
897
Geoff Langc1984ed2016-10-07 12:41:00 -0400898 default:
899 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
900 return false;
901 }
902
903 return true;
904}
905
906template <typename ParamType>
907bool ValidateSamplerParameterBase(Context *context,
908 GLuint sampler,
909 GLenum pname,
910 GLsizei bufSize,
911 ParamType *params)
912{
913 if (context->getClientMajorVersion() < 3)
914 {
915 context->handleError(
916 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
917 return false;
918 }
919
920 if (!context->isSampler(sampler))
921 {
922 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
923 return false;
924 }
925
926 const GLsizei minBufSize = 1;
927 if (bufSize >= 0 && bufSize < minBufSize)
928 {
929 context->handleError(
930 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
931 return false;
932 }
933
934 switch (pname)
935 {
936 case GL_TEXTURE_WRAP_S:
937 case GL_TEXTURE_WRAP_T:
938 case GL_TEXTURE_WRAP_R:
939 if (!ValidateTextureWrapModeValue(context, params, false))
940 {
941 return false;
942 }
943 break;
944
945 case GL_TEXTURE_MIN_FILTER:
946 if (!ValidateTextureMinFilterValue(context, params, false))
947 {
948 return false;
949 }
950 break;
951
952 case GL_TEXTURE_MAG_FILTER:
953 if (!ValidateTextureMagFilterValue(context, params))
954 {
955 return false;
956 }
957 break;
958
959 case GL_TEXTURE_MIN_LOD:
960 case GL_TEXTURE_MAX_LOD:
961 // any value is permissible
962 break;
963
964 case GL_TEXTURE_COMPARE_MODE:
965 if (!ValidateTextureCompareModeValue(context, params))
966 {
967 return false;
968 }
969 break;
970
971 case GL_TEXTURE_COMPARE_FUNC:
972 if (!ValidateTextureCompareFuncValue(context, params))
973 {
974 return false;
975 }
976 break;
977
Geoff Lang81c6b572016-10-19 14:07:52 -0700978 case GL_TEXTURE_SRGB_DECODE_EXT:
979 if (!ValidateTextureSRGBDecodeValue(context, params))
980 {
981 return false;
982 }
983 break;
984
Geoff Langc1984ed2016-10-07 12:41:00 -0400985 default:
986 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
987 return false;
988 }
989
990 return true;
991}
992
993bool ValidateGetSamplerParameterBase(Context *context,
994 GLuint sampler,
995 GLenum pname,
996 GLsizei *length)
997{
998 if (length)
999 {
1000 *length = 0;
1001 }
1002
1003 if (context->getClientMajorVersion() < 3)
1004 {
1005 context->handleError(
1006 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1007 return false;
1008 }
1009
1010 if (!context->isSampler(sampler))
1011 {
1012 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
1013 return false;
1014 }
1015
1016 switch (pname)
1017 {
1018 case GL_TEXTURE_WRAP_S:
1019 case GL_TEXTURE_WRAP_T:
1020 case GL_TEXTURE_WRAP_R:
1021 case GL_TEXTURE_MIN_FILTER:
1022 case GL_TEXTURE_MAG_FILTER:
1023 case GL_TEXTURE_MIN_LOD:
1024 case GL_TEXTURE_MAX_LOD:
1025 case GL_TEXTURE_COMPARE_MODE:
1026 case GL_TEXTURE_COMPARE_FUNC:
1027 break;
1028
Geoff Lang81c6b572016-10-19 14:07:52 -07001029 case GL_TEXTURE_SRGB_DECODE_EXT:
1030 if (!context->getExtensions().textureSRGBDecode)
1031 {
1032 context->handleError(
1033 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
1034 return false;
1035 }
1036 break;
1037
Geoff Langc1984ed2016-10-07 12:41:00 -04001038 default:
1039 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1040 return false;
1041 }
1042
1043 if (length)
1044 {
1045 *length = 1;
1046 }
1047 return true;
1048}
1049
Geoff Lang0b031062016-10-13 14:30:04 -04001050bool ValidateGetVertexAttribBase(Context *context,
1051 GLuint index,
1052 GLenum pname,
1053 GLsizei *length,
1054 bool pointer,
1055 bool pureIntegerEntryPoint)
1056{
1057 if (length)
1058 {
1059 *length = 0;
1060 }
1061
1062 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1063 {
1064 context->handleError(
1065 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1066 return false;
1067 }
1068
1069 if (index >= context->getCaps().maxVertexAttributes)
1070 {
1071 context->handleError(Error(
1072 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1073 return false;
1074 }
1075
1076 if (pointer)
1077 {
1078 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1079 {
1080 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1081 return false;
1082 }
1083 }
1084 else
1085 {
1086 switch (pname)
1087 {
1088 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1089 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1090 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1091 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1092 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1093 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1094 case GL_CURRENT_VERTEX_ATTRIB:
1095 break;
1096
1097 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1098 static_assert(
1099 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1100 "ANGLE extension enums not equal to GL enums.");
1101 if (context->getClientMajorVersion() < 3 &&
1102 !context->getExtensions().instancedArrays)
1103 {
1104 context->handleError(Error(GL_INVALID_ENUM,
1105 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1106 "3.0 or GL_ANGLE_instanced_arrays."));
1107 return false;
1108 }
1109 break;
1110
1111 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1112 if (context->getClientMajorVersion() < 3)
1113 {
Shao80957d92017-02-20 21:25:59 +08001114 context->handleError(Error(
1115 GL_INVALID_ENUM, "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0."));
1116 return false;
1117 }
1118 break;
1119
1120 case GL_VERTEX_ATTRIB_BINDING:
1121 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
1122 if (context->getClientVersion() < ES_3_1)
1123 {
1124 context->handleError(
1125 Error(GL_INVALID_ENUM, "Vertex Attrib Bindings require OpenGL ES 3.1."));
Geoff Lang0b031062016-10-13 14:30:04 -04001126 return false;
1127 }
1128 break;
1129
1130 default:
1131 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1132 return false;
1133 }
1134 }
1135
1136 if (length)
1137 {
1138 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1139 {
1140 *length = 4;
1141 }
1142 else
1143 {
1144 *length = 1;
1145 }
1146 }
1147
1148 return true;
1149}
1150
Geoff Lang6899b872016-10-14 11:30:13 -04001151bool ValidateGetActiveUniformBlockivBase(Context *context,
1152 GLuint program,
1153 GLuint uniformBlockIndex,
1154 GLenum pname,
1155 GLsizei *length)
1156{
1157 if (length)
1158 {
1159 *length = 0;
1160 }
1161
1162 if (context->getClientMajorVersion() < 3)
1163 {
1164 context->handleError(
1165 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1166 return false;
1167 }
1168
1169 Program *programObject = GetValidProgram(context, program);
1170 if (!programObject)
1171 {
1172 return false;
1173 }
1174
1175 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1176 {
1177 context->handleError(
1178 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1179 return false;
1180 }
1181
1182 switch (pname)
1183 {
1184 case GL_UNIFORM_BLOCK_BINDING:
1185 case GL_UNIFORM_BLOCK_DATA_SIZE:
1186 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1187 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1188 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1189 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1190 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1191 break;
1192
1193 default:
1194 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1195 return false;
1196 }
1197
1198 if (length)
1199 {
1200 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1201 {
1202 const UniformBlock &uniformBlock =
1203 programObject->getUniformBlockByIndex(uniformBlockIndex);
1204 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1205 }
1206 else
1207 {
1208 *length = 1;
1209 }
1210 }
1211
1212 return true;
1213}
1214
Geoff Langebebe1c2016-10-14 12:01:31 -04001215bool ValidateGetBufferParameterBase(ValidationContext *context,
1216 GLenum target,
1217 GLenum pname,
1218 bool pointerVersion,
1219 GLsizei *numParams)
1220{
1221 if (numParams)
1222 {
1223 *numParams = 0;
1224 }
1225
1226 if (!ValidBufferTarget(context, target))
1227 {
1228 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1229 return false;
1230 }
1231
1232 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1233 if (!buffer)
1234 {
1235 // A null buffer means that "0" is bound to the requested buffer target
1236 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1237 return false;
1238 }
1239
1240 const Extensions &extensions = context->getExtensions();
1241
1242 switch (pname)
1243 {
1244 case GL_BUFFER_USAGE:
1245 case GL_BUFFER_SIZE:
1246 break;
1247
1248 case GL_BUFFER_ACCESS_OES:
1249 if (!extensions.mapBuffer)
1250 {
1251 context->handleError(
Jamie Madillcc6ac252017-01-25 12:57:21 -08001252 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001253 return false;
1254 }
1255 break;
1256
1257 case GL_BUFFER_MAPPED:
1258 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1259 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1260 !extensions.mapBufferRange)
1261 {
1262 context->handleError(Error(
1263 GL_INVALID_ENUM,
Jamie Madillcc6ac252017-01-25 12:57:21 -08001264 "pname requires OpenGL ES 3.0, GL_OES_mapbuffer or GL_EXT_map_buffer_range."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001265 return false;
1266 }
1267 break;
1268
1269 case GL_BUFFER_MAP_POINTER:
1270 if (!pointerVersion)
1271 {
1272 context->handleError(
1273 Error(GL_INVALID_ENUM,
1274 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1275 return false;
1276 }
1277 break;
1278
1279 case GL_BUFFER_ACCESS_FLAGS:
1280 case GL_BUFFER_MAP_OFFSET:
1281 case GL_BUFFER_MAP_LENGTH:
1282 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1283 {
1284 context->handleError(Error(
1285 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1286 return false;
1287 }
1288 break;
1289
1290 default:
1291 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1292 return false;
1293 }
1294
1295 // All buffer parameter queries return one value.
1296 if (numParams)
1297 {
1298 *numParams = 1;
1299 }
1300
1301 return true;
1302}
1303
Geoff Lang0a9661f2016-10-20 10:59:20 -07001304bool ValidateGetInternalFormativBase(Context *context,
1305 GLenum target,
1306 GLenum internalformat,
1307 GLenum pname,
1308 GLsizei bufSize,
1309 GLsizei *numParams)
1310{
1311 if (numParams)
1312 {
1313 *numParams = 0;
1314 }
1315
1316 if (context->getClientMajorVersion() < 3)
1317 {
1318 context->handleError(
1319 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1320 return false;
1321 }
1322
1323 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1324 if (!formatCaps.renderable)
1325 {
1326 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1327 return false;
1328 }
1329
1330 switch (target)
1331 {
1332 case GL_RENDERBUFFER:
1333 break;
1334
JiangYizhoubddc46b2016-12-09 09:50:51 +08001335 case GL_TEXTURE_2D_MULTISAMPLE:
1336 if (context->getClientVersion() < ES_3_1)
1337 {
1338 context->handleError(
1339 Error(GL_INVALID_OPERATION, "Texture target requires at least OpenGL ES 3.1."));
1340 return false;
1341 }
1342 break;
1343
Geoff Lang0a9661f2016-10-20 10:59:20 -07001344 default:
1345 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1346 return false;
1347 }
1348
1349 if (bufSize < 0)
1350 {
1351 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1352 return false;
1353 }
1354
1355 GLsizei maxWriteParams = 0;
1356 switch (pname)
1357 {
1358 case GL_NUM_SAMPLE_COUNTS:
1359 maxWriteParams = 1;
1360 break;
1361
1362 case GL_SAMPLES:
1363 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1364 break;
1365
1366 default:
1367 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1368 return false;
1369 }
1370
1371 if (numParams)
1372 {
1373 // glGetInternalFormativ will not overflow bufSize
1374 *numParams = std::min(bufSize, maxWriteParams);
1375 }
1376
1377 return true;
1378}
1379
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001380bool ValidateUniformCommonBase(gl::Context *context,
1381 gl::Program *program,
1382 GLint location,
1383 GLsizei count,
1384 const LinkedUniform **uniformOut)
1385{
1386 // TODO(Jiajia): Add image uniform check in future.
1387 if (count < 0)
1388 {
1389 context->handleError(Error(GL_INVALID_VALUE));
1390 return false;
1391 }
1392
1393 if (!program || !program->isLinked())
1394 {
1395 context->handleError(Error(GL_INVALID_OPERATION));
1396 return false;
1397 }
1398
1399 if (location == -1)
1400 {
1401 // Silently ignore the uniform command
1402 return false;
1403 }
1404
1405 const auto &uniformLocations = program->getUniformLocations();
1406 size_t castedLocation = static_cast<size_t>(location);
1407 if (castedLocation >= uniformLocations.size())
1408 {
1409 context->handleError(Error(GL_INVALID_OPERATION, "Invalid uniform location"));
1410 return false;
1411 }
1412
1413 const auto &uniformLocation = uniformLocations[castedLocation];
1414 if (uniformLocation.ignored)
1415 {
1416 // Silently ignore the uniform command
1417 return false;
1418 }
1419
1420 if (!uniformLocation.used)
1421 {
1422 context->handleError(Error(GL_INVALID_OPERATION));
1423 return false;
1424 }
1425
1426 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
1427
1428 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
1429 if (!uniform.isArray() && count > 1)
1430 {
1431 context->handleError(Error(GL_INVALID_OPERATION));
1432 return false;
1433 }
1434
1435 *uniformOut = &uniform;
1436 return true;
1437}
1438
Frank Henigman999b0fd2017-02-02 21:45:55 -05001439bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -05001440 GLenum uniformType,
1441 GLsizei count,
1442 const GLint *value)
1443{
1444 // Value type is GL_INT, because we only get here from glUniform1i{v}.
1445 // It is compatible with INT or BOOL.
1446 // Do these cheap tests first, for a little extra speed.
1447 if (GL_INT == uniformType || GL_BOOL == uniformType)
1448 {
1449 return true;
1450 }
1451
1452 if (IsSamplerType(uniformType))
1453 {
Frank Henigman999b0fd2017-02-02 21:45:55 -05001454 // Check that the values are in range.
1455 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
1456 for (GLsizei i = 0; i < count; ++i)
1457 {
1458 if (value[i] < 0 || value[i] >= max)
1459 {
1460 context->handleError(Error(GL_INVALID_VALUE, "sampler uniform value out of range"));
1461 return false;
1462 }
1463 }
Frank Henigmana98a6472017-02-02 21:38:32 -05001464 return true;
1465 }
1466
1467 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1468 return false;
1469}
1470
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001471bool ValidateUniformValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1472{
1473 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -05001474 // Do the cheaper test first, for a little extra speed.
1475 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001476 {
1477 return true;
1478 }
1479
1480 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1481 return false;
1482}
1483
1484bool ValidateUniformMatrixValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1485{
1486 // Check that the value type is compatible with uniform type.
1487 if (valueType == uniformType)
1488 {
1489 return true;
1490 }
1491
1492 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1493 return false;
1494}
1495
Geoff Langf41a7152016-09-19 15:11:17 -04001496} // anonymous namespace
1497
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001498bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001499{
Jamie Madilld7460c72014-01-21 16:38:14 -05001500 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001501 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001502 case GL_TEXTURE_2D:
1503 case GL_TEXTURE_CUBE_MAP:
1504 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001505
He Yunchaoced53ae2016-11-29 15:00:51 +08001506 case GL_TEXTURE_3D:
1507 case GL_TEXTURE_2D_ARRAY:
1508 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001509
He Yunchaoced53ae2016-11-29 15:00:51 +08001510 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001511 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001512
He Yunchaoced53ae2016-11-29 15:00:51 +08001513 default:
1514 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001515 }
Jamie Madill35d15012013-10-07 10:46:37 -04001516}
1517
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001518bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1519{
1520 switch (target)
1521 {
1522 case GL_TEXTURE_2D:
1523 case GL_TEXTURE_CUBE_MAP:
1524 return true;
1525
1526 default:
1527 return false;
1528 }
1529}
1530
1531bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1532{
1533 switch (target)
1534 {
1535 case GL_TEXTURE_3D:
1536 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001537 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001538
1539 default:
1540 return false;
1541 }
1542}
1543
Ian Ewellbda75592016-04-18 17:25:54 -04001544// Most texture GL calls are not compatible with external textures, so we have a separate validation
1545// function for use in the GL calls that do
1546bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1547{
1548 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1549 (context->getExtensions().eglImageExternal ||
1550 context->getExtensions().eglStreamConsumerExternal);
1551}
1552
Shannon Woods4dfed832014-03-17 20:03:39 -04001553// This function differs from ValidTextureTarget in that the target must be
1554// usable as the destination of a 2D operation-- so a cube face is valid, but
1555// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001556// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001557bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001558{
1559 switch (target)
1560 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001561 case GL_TEXTURE_2D:
1562 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1563 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1564 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1565 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1566 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1567 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1568 return true;
1569 default:
1570 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001571 }
1572}
1573
1574bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1575{
1576 switch (target)
1577 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001578 case GL_TEXTURE_3D:
1579 case GL_TEXTURE_2D_ARRAY:
1580 return true;
1581 default:
1582 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001583 }
1584}
1585
He Yunchao11b038b2016-11-22 21:24:04 +08001586bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1587{
1588 switch (target)
1589 {
1590 case GL_TEXTURE_2D:
1591 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1592 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1593 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1594 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1595 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1596 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1597 case GL_TEXTURE_3D:
1598 case GL_TEXTURE_2D_ARRAY:
1599 case GL_TEXTURE_2D_MULTISAMPLE:
1600 return true;
1601 default:
1602 return false;
1603 }
1604}
1605
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001606bool ValidFramebufferTarget(GLenum target)
1607{
He Yunchaoced53ae2016-11-29 15:00:51 +08001608 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1609 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001610 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001611
1612 switch (target)
1613 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001614 case GL_FRAMEBUFFER:
1615 return true;
1616 case GL_READ_FRAMEBUFFER:
1617 return true;
1618 case GL_DRAW_FRAMEBUFFER:
1619 return true;
1620 default:
1621 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001622 }
1623}
1624
Jamie Madill29639852016-09-02 15:00:09 -04001625bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001626{
1627 switch (target)
1628 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001629 case GL_ARRAY_BUFFER:
1630 case GL_ELEMENT_ARRAY_BUFFER:
1631 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001632
He Yunchaoced53ae2016-11-29 15:00:51 +08001633 case GL_PIXEL_PACK_BUFFER:
1634 case GL_PIXEL_UNPACK_BUFFER:
1635 return (context->getExtensions().pixelBufferObject ||
1636 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001637
He Yunchaoced53ae2016-11-29 15:00:51 +08001638 case GL_COPY_READ_BUFFER:
1639 case GL_COPY_WRITE_BUFFER:
1640 case GL_TRANSFORM_FEEDBACK_BUFFER:
1641 case GL_UNIFORM_BUFFER:
1642 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001643
He Yunchaoced53ae2016-11-29 15:00:51 +08001644 case GL_ATOMIC_COUNTER_BUFFER:
1645 case GL_SHADER_STORAGE_BUFFER:
1646 case GL_DRAW_INDIRECT_BUFFER:
1647 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001648 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001649
He Yunchaoced53ae2016-11-29 15:00:51 +08001650 default:
1651 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001652 }
1653}
1654
Jamie Madillc29968b2016-01-20 11:17:23 -05001655bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001656{
Jamie Madillc29968b2016-01-20 11:17:23 -05001657 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001658 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001659 switch (target)
1660 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001661 case GL_TEXTURE_2D:
1662 maxDimension = caps.max2DTextureSize;
1663 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001664 case GL_TEXTURE_CUBE_MAP:
1665 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1666 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1667 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1668 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1669 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1670 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1671 maxDimension = caps.maxCubeMapTextureSize;
1672 break;
1673 case GL_TEXTURE_3D:
1674 maxDimension = caps.max3DTextureSize;
1675 break;
1676 case GL_TEXTURE_2D_ARRAY:
1677 maxDimension = caps.max2DTextureSize;
1678 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001679 case GL_TEXTURE_2D_MULTISAMPLE:
1680 maxDimension = caps.max2DTextureSize;
1681 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001682 default:
1683 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001684 }
1685
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001686 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001687}
1688
Geoff Langcc507aa2016-12-12 10:09:52 -05001689bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001690 GLenum target,
1691 GLint level,
1692 GLsizei width,
1693 GLsizei height,
1694 GLsizei depth,
1695 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001696{
1697 if (level < 0 || width < 0 || height < 0 || depth < 0)
1698 {
1699 return false;
1700 }
1701
Austin Kinross08528e12015-10-07 16:24:40 -07001702 // TexSubImage parameters can be NPOT without textureNPOT extension,
1703 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001704 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001705 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001706 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001707 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001708 {
1709 return false;
1710 }
1711
1712 if (!ValidMipLevel(context, target, level))
1713 {
1714 return false;
1715 }
1716
1717 return true;
1718}
1719
Geoff Lang0d8b7242015-09-09 14:56:53 -04001720bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1721{
1722 // List of compressed format that require that the texture size is smaller than or a multiple of
1723 // the compressed block size.
1724 switch (internalFormat)
1725 {
1726 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1727 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1728 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1729 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001730 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001731 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1732 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1733 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1734 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1735 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
1736 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001737 return true;
1738
1739 default:
1740 return false;
1741 }
1742}
1743
Jamie Madillc29968b2016-01-20 11:17:23 -05001744bool ValidCompressedImageSize(const ValidationContext *context,
1745 GLenum internalFormat,
Geoff Lang44ff5a72017-02-03 15:15:43 -05001746 GLint xoffset,
1747 GLint yoffset,
Jamie Madillc29968b2016-01-20 11:17:23 -05001748 GLsizei width,
1749 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001750{
Geoff Lang5d601382014-07-22 15:14:06 -04001751 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1752 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001753 {
1754 return false;
1755 }
1756
Geoff Lang44ff5a72017-02-03 15:15:43 -05001757 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001758 {
1759 return false;
1760 }
1761
Geoff Lang0d8b7242015-09-09 14:56:53 -04001762 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1763 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001764 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
1765 yoffset % formatInfo.compressedBlockHeight != 0 ||
1766 (static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
Geoff Lang0d8b7242015-09-09 14:56:53 -04001767 width % formatInfo.compressedBlockWidth != 0) ||
1768 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1769 height % formatInfo.compressedBlockHeight != 0))
1770 {
1771 return false;
1772 }
1773 }
1774
Geoff Langd4f180b2013-09-24 13:57:44 -04001775 return true;
1776}
1777
Geoff Langff5b2d52016-09-07 11:32:23 -04001778bool ValidImageDataSize(ValidationContext *context,
1779 GLenum textureTarget,
1780 GLsizei width,
1781 GLsizei height,
1782 GLsizei depth,
1783 GLenum internalFormat,
1784 GLenum type,
1785 const GLvoid *pixels,
1786 GLsizei imageSize)
1787{
1788 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1789 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1790 {
1791 // Checks are not required
1792 return true;
1793 }
1794
1795 // ...the data would be unpacked from the buffer object such that the memory reads required
1796 // would exceed the data store size.
1797 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1798 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1799 const gl::Extents size(width, height, depth);
1800 const auto &unpack = context->getGLState().getUnpackState();
1801
1802 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1803 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1804 if (endByteOrErr.isError())
1805 {
1806 context->handleError(endByteOrErr.getError());
1807 return false;
1808 }
1809
1810 GLuint endByte = endByteOrErr.getResult();
1811
1812 if (pixelUnpackBuffer)
1813 {
1814 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1815 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1816 checkedEndByte += checkedOffset;
1817
1818 if (!checkedEndByte.IsValid() ||
1819 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1820 {
1821 // Overflow past the end of the buffer
1822 context->handleError(Error(GL_INVALID_OPERATION));
1823 return false;
1824 }
1825 }
1826 else
1827 {
1828 ASSERT(imageSize >= 0);
1829 if (pixels == nullptr && imageSize != 0)
1830 {
1831 context->handleError(
1832 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001833 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001834 }
1835
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001836 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001837 {
1838 context->handleError(
1839 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1840 return false;
1841 }
1842 }
1843
1844 return true;
1845}
1846
Geoff Lang37dde692014-01-31 16:34:54 -05001847bool ValidQueryType(const Context *context, GLenum queryType)
1848{
He Yunchaoced53ae2016-11-29 15:00:51 +08001849 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1850 "GL extension enums not equal.");
1851 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1852 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001853
1854 switch (queryType)
1855 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001856 case GL_ANY_SAMPLES_PASSED:
1857 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1858 return true;
1859 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1860 return (context->getClientMajorVersion() >= 3);
1861 case GL_TIME_ELAPSED_EXT:
1862 return context->getExtensions().disjointTimerQuery;
1863 case GL_COMMANDS_COMPLETED_CHROMIUM:
1864 return context->getExtensions().syncQuery;
1865 default:
1866 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001867 }
1868}
1869
Jamie Madillef300b12016-10-07 15:12:09 -04001870Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001871{
He Yunchaoced53ae2016-11-29 15:00:51 +08001872 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1873 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1874 // or program object and INVALID_OPERATION if the provided name identifies an object
1875 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001876
Dian Xiang769769a2015-09-09 15:20:08 -07001877 Program *validProgram = context->getProgram(id);
1878
1879 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001880 {
Dian Xiang769769a2015-09-09 15:20:08 -07001881 if (context->getShader(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 program name, but found a shader name"));
1885 }
1886 else
1887 {
Jamie Madill437fa652016-05-03 15:13:24 -04001888 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
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 validProgram;
1893}
1894
Jamie Madillef300b12016-10-07 15:12:09 -04001895Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001896{
1897 // See ValidProgram for spec details.
1898
1899 Shader *validShader = context->getShader(id);
1900
1901 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001902 {
Dian Xiang769769a2015-09-09 15:20:08 -07001903 if (context->getProgram(id))
1904 {
Jamie Madill437fa652016-05-03 15:13:24 -04001905 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001906 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1907 }
1908 else
1909 {
Jamie Madill437fa652016-05-03 15:13:24 -04001910 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001911 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001912 }
Dian Xiang769769a2015-09-09 15:20:08 -07001913
1914 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001915}
1916
Geoff Langb1196682014-07-23 13:47:29 -04001917bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001918{
1919 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1920 {
1921 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1922
Geoff Langaae65a42014-05-26 12:43:44 -04001923 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001924 {
Jamie Madill437fa652016-05-03 15:13:24 -04001925 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001926 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001927 }
1928 }
1929 else
1930 {
1931 switch (attachment)
1932 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001933 case GL_DEPTH_ATTACHMENT:
1934 case GL_STENCIL_ATTACHMENT:
1935 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001936
He Yunchaoced53ae2016-11-29 15:00:51 +08001937 case GL_DEPTH_STENCIL_ATTACHMENT:
1938 if (!context->getExtensions().webglCompatibility &&
1939 context->getClientMajorVersion() < 3)
1940 {
1941 context->handleError(Error(GL_INVALID_ENUM));
1942 return false;
1943 }
1944 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001945
He Yunchaoced53ae2016-11-29 15:00:51 +08001946 default:
1947 context->handleError(Error(GL_INVALID_ENUM));
1948 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001949 }
1950 }
1951
1952 return true;
1953}
1954
Jamie Madille8fb6402017-02-14 17:56:40 -05001955bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001956 GLenum target,
1957 GLsizei samples,
1958 GLenum internalformat,
1959 GLsizei width,
1960 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001961{
1962 switch (target)
1963 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001964 case GL_RENDERBUFFER:
1965 break;
1966 default:
1967 context->handleError(Error(GL_INVALID_ENUM));
1968 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001969 }
1970
1971 if (width < 0 || height < 0 || samples < 0)
1972 {
Jamie Madill437fa652016-05-03 15:13:24 -04001973 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001974 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001975 }
1976
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001977 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1978 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1979
1980 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001981 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001982 {
Jamie Madill437fa652016-05-03 15:13:24 -04001983 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001984 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001985 }
1986
1987 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1988 // 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 -08001989 // only sized internal formats.
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001990 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(convertedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04001991 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001992 {
Jamie Madill437fa652016-05-03 15:13:24 -04001993 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001994 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001995 }
1996
Geoff Langaae65a42014-05-26 12:43:44 -04001997 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001998 {
Jamie Madill437fa652016-05-03 15:13:24 -04001999 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002000 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002001 }
2002
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002003 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002004 if (handle == 0)
2005 {
Jamie Madill437fa652016-05-03 15:13:24 -04002006 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002007 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002008 }
2009
2010 return true;
2011}
2012
He Yunchaoced53ae2016-11-29 15:00:51 +08002013bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
2014 GLenum target,
2015 GLenum attachment,
2016 GLenum renderbuffertarget,
2017 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002018{
Shannon Woods1da3cf62014-06-27 15:32:23 -04002019 if (!ValidFramebufferTarget(target))
2020 {
Jamie Madill437fa652016-05-03 15:13:24 -04002021 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002022 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04002023 }
2024
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002025 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002026
Jamie Madill84115c92015-04-23 15:00:07 -04002027 ASSERT(framebuffer);
2028 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002029 {
Jamie Madill437fa652016-05-03 15:13:24 -04002030 context->handleError(
2031 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002032 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002033 }
2034
Jamie Madillb4472272014-07-03 10:38:55 -04002035 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002036 {
Jamie Madillb4472272014-07-03 10:38:55 -04002037 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002038 }
2039
Jamie Madillab9d82c2014-01-21 16:38:14 -05002040 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2041 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2042 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2043 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2044 if (renderbuffer != 0)
2045 {
2046 if (!context->getRenderbuffer(renderbuffer))
2047 {
Jamie Madill437fa652016-05-03 15:13:24 -04002048 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002049 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05002050 }
2051 }
2052
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002053 return true;
2054}
2055
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002056bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002057 GLint srcX0,
2058 GLint srcY0,
2059 GLint srcX1,
2060 GLint srcY1,
2061 GLint dstX0,
2062 GLint dstY0,
2063 GLint dstX1,
2064 GLint dstY1,
2065 GLbitfield mask,
2066 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002067{
2068 switch (filter)
2069 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002070 case GL_NEAREST:
2071 break;
2072 case GL_LINEAR:
2073 break;
2074 default:
2075 context->handleError(Error(GL_INVALID_ENUM));
2076 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002077 }
2078
2079 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
2080 {
Jamie Madill437fa652016-05-03 15:13:24 -04002081 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002082 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002083 }
2084
2085 if (mask == 0)
2086 {
2087 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
2088 // buffers are copied.
2089 return false;
2090 }
2091
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002092 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
2093 // color buffer, leaving only nearest being unfiltered from above
2094 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
2095 {
Jamie Madill437fa652016-05-03 15:13:24 -04002096 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002097 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002098 }
2099
Jamie Madill51f40ec2016-06-15 14:06:00 -04002100 const auto &glState = context->getGLState();
2101 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2102 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05002103
2104 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002105 {
Jamie Madill437fa652016-05-03 15:13:24 -04002106 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002107 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002108 }
2109
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002110 if (readFramebuffer->id() == drawFramebuffer->id())
2111 {
2112 context->handleError(Error(GL_INVALID_OPERATION));
2113 return false;
2114 }
2115
Jamie Madill51f40ec2016-06-15 14:06:00 -04002116 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002117 {
Jamie Madill437fa652016-05-03 15:13:24 -04002118 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002119 return false;
2120 }
2121
Jamie Madill51f40ec2016-06-15 14:06:00 -04002122 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002123 {
Jamie Madill437fa652016-05-03 15:13:24 -04002124 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002125 return false;
2126 }
2127
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002128 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002129 {
Jamie Madill437fa652016-05-03 15:13:24 -04002130 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002131 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002132 }
2133
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002134 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2135
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002136 if (mask & GL_COLOR_BUFFER_BIT)
2137 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002138 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002139 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002140
He Yunchao66a41a22016-12-15 16:45:05 +08002141 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002142 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002143 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002144
Geoff Langa15472a2015-08-11 11:48:03 -04002145 for (size_t drawbufferIdx = 0;
2146 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002147 {
Geoff Langa15472a2015-08-11 11:48:03 -04002148 const FramebufferAttachment *attachment =
2149 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2150 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002151 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002152 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002153
Geoff Langb2f3d052013-08-13 12:49:27 -04002154 // The GL ES 3.0.2 spec (pg 193) states that:
2155 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002156 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2157 // as well
2158 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2159 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002160 // Changes with EXT_color_buffer_float:
2161 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002162 GLenum readComponentType = readFormat.info->componentType;
2163 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002164 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002165 readComponentType == GL_SIGNED_NORMALIZED);
2166 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2167 drawComponentType == GL_SIGNED_NORMALIZED);
2168
2169 if (extensions.colorBufferFloat)
2170 {
2171 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2172 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2173
2174 if (readFixedOrFloat != drawFixedOrFloat)
2175 {
Jamie Madill437fa652016-05-03 15:13:24 -04002176 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002177 "If the read buffer contains fixed-point or "
2178 "floating-point values, the draw buffer "
2179 "must as well."));
2180 return false;
2181 }
2182 }
2183 else if (readFixedPoint != drawFixedPoint)
2184 {
Jamie Madill437fa652016-05-03 15:13:24 -04002185 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002186 "If the read buffer contains fixed-point "
2187 "values, the draw buffer must as well."));
2188 return false;
2189 }
2190
2191 if (readComponentType == GL_UNSIGNED_INT &&
2192 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002193 {
Jamie Madill437fa652016-05-03 15:13:24 -04002194 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002195 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002196 }
2197
Jamie Madill6163c752015-12-07 16:32:59 -05002198 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002199 {
Jamie Madill437fa652016-05-03 15:13:24 -04002200 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002201 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002202 }
2203
Jamie Madilla3944d42016-07-22 22:13:26 -04002204 if (readColorBuffer->getSamples() > 0 &&
2205 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002206 {
Jamie Madill437fa652016-05-03 15:13:24 -04002207 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002208 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002209 }
2210 }
2211 }
2212
Jamie Madilla3944d42016-07-22 22:13:26 -04002213 if ((readFormat.info->componentType == GL_INT ||
2214 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2215 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002216 {
Jamie Madill437fa652016-05-03 15:13:24 -04002217 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002218 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002219 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002220 }
He Yunchao66a41a22016-12-15 16:45:05 +08002221 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2222 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2223 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2224 // situation is an application error that would lead to a crash in ANGLE.
2225 else if (drawFramebuffer->hasEnabledDrawBuffer())
2226 {
2227 context->handleError(Error(
2228 GL_INVALID_OPERATION,
2229 "Attempt to read from a missing color attachment of a complete framebuffer."));
2230 return false;
2231 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002232 }
2233
He Yunchaoced53ae2016-11-29 15:00:51 +08002234 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002235 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2236 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002237 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002238 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002239 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002240 const gl::FramebufferAttachment *readBuffer =
2241 readFramebuffer->getAttachment(attachments[i]);
2242 const gl::FramebufferAttachment *drawBuffer =
2243 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002244
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002245 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002246 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002247 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002248 {
Jamie Madill437fa652016-05-03 15:13:24 -04002249 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002250 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002251 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002252
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002253 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002254 {
Jamie Madill437fa652016-05-03 15:13:24 -04002255 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002256 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002257 }
2258 }
He Yunchao66a41a22016-12-15 16:45:05 +08002259 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2260 else if (drawBuffer)
2261 {
2262 context->handleError(Error(GL_INVALID_OPERATION,
2263 "Attempt to read from a missing depth/stencil "
2264 "attachment of a complete framebuffer."));
2265 return false;
2266 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002267 }
2268 }
2269
2270 return true;
2271}
2272
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002273bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002274 GLint x,
2275 GLint y,
2276 GLsizei width,
2277 GLsizei height,
2278 GLenum format,
2279 GLenum type,
2280 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002281{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002282 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2283}
2284
2285bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2286 GLint x,
2287 GLint y,
2288 GLsizei width,
2289 GLsizei height,
2290 GLenum format,
2291 GLenum type,
2292 GLsizei bufSize,
2293 GLsizei *length,
2294 GLvoid *pixels)
2295{
2296 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002297 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002298 return false;
2299 }
2300
Geoff Lang62fce5b2016-09-30 10:46:35 -04002301 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2302 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002303 {
Geoff Langb1196682014-07-23 13:47:29 -04002304 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002305 }
2306
Geoff Lang62fce5b2016-09-30 10:46:35 -04002307 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002308 {
Geoff Langb1196682014-07-23 13:47:29 -04002309 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002310 }
2311
Jamie Madillc29968b2016-01-20 11:17:23 -05002312 return true;
2313}
2314
2315bool ValidateReadnPixelsEXT(Context *context,
2316 GLint x,
2317 GLint y,
2318 GLsizei width,
2319 GLsizei height,
2320 GLenum format,
2321 GLenum type,
2322 GLsizei bufSize,
2323 GLvoid *pixels)
2324{
2325 if (bufSize < 0)
2326 {
Jamie Madill437fa652016-05-03 15:13:24 -04002327 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002328 return false;
2329 }
2330
Geoff Lang62fce5b2016-09-30 10:46:35 -04002331 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2332 pixels);
2333}
Jamie Madill26e91952014-03-05 15:01:27 -05002334
Geoff Lang62fce5b2016-09-30 10:46:35 -04002335bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2336 GLint x,
2337 GLint y,
2338 GLsizei width,
2339 GLsizei height,
2340 GLenum format,
2341 GLenum type,
2342 GLsizei bufSize,
2343 GLsizei *length,
2344 GLvoid *data)
2345{
2346 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002347 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002348 return false;
2349 }
2350
Geoff Lang62fce5b2016-09-30 10:46:35 -04002351 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002352 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002353 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002354 }
2355
Geoff Lang62fce5b2016-09-30 10:46:35 -04002356 if (!ValidateRobustBufferSize(context, bufSize, *length))
2357 {
2358 return false;
2359 }
2360
2361 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002362}
2363
Olli Etuaho41997e72016-03-10 13:38:39 +02002364bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002365{
2366 if (!context->getExtensions().occlusionQueryBoolean &&
2367 !context->getExtensions().disjointTimerQuery)
2368 {
Jamie Madill437fa652016-05-03 15:13:24 -04002369 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002370 return false;
2371 }
2372
Olli Etuaho41997e72016-03-10 13:38:39 +02002373 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002374}
2375
Olli Etuaho41997e72016-03-10 13:38:39 +02002376bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002377{
2378 if (!context->getExtensions().occlusionQueryBoolean &&
2379 !context->getExtensions().disjointTimerQuery)
2380 {
Jamie Madill437fa652016-05-03 15:13:24 -04002381 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002382 return false;
2383 }
2384
Olli Etuaho41997e72016-03-10 13:38:39 +02002385 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002386}
2387
2388bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002389{
2390 if (!ValidQueryType(context, target))
2391 {
Jamie Madill437fa652016-05-03 15:13:24 -04002392 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002393 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002394 }
2395
2396 if (id == 0)
2397 {
Jamie Madill437fa652016-05-03 15:13:24 -04002398 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002399 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002400 }
2401
2402 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2403 // of zero, if the active query object name for <target> is non-zero (for the
2404 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2405 // the active query for either target is non-zero), if <id> is the name of an
2406 // existing query object whose type does not match <target>, or if <id> is the
2407 // active query object name for any query type, the error INVALID_OPERATION is
2408 // generated.
2409
2410 // Ensure no other queries are active
2411 // NOTE: If other queries than occlusion are supported, we will need to check
2412 // separately that:
2413 // a) The query ID passed is not the current active query for any target/type
2414 // b) There are no active queries for the requested target (and in the case
2415 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2416 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002417
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002418 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002419 {
Jamie Madill437fa652016-05-03 15:13:24 -04002420 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002421 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002422 }
2423
2424 Query *queryObject = context->getQuery(id, true, target);
2425
2426 // check that name was obtained with glGenQueries
2427 if (!queryObject)
2428 {
Jamie Madill437fa652016-05-03 15:13:24 -04002429 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002430 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002431 }
2432
2433 // check for type mismatch
2434 if (queryObject->getType() != target)
2435 {
Jamie Madill437fa652016-05-03 15:13:24 -04002436 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002437 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002438 }
2439
2440 return true;
2441}
2442
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002443bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2444{
2445 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002446 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002447 {
Jamie Madill437fa652016-05-03 15:13:24 -04002448 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002449 return false;
2450 }
2451
2452 return ValidateBeginQueryBase(context, target, id);
2453}
2454
2455bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002456{
2457 if (!ValidQueryType(context, target))
2458 {
Jamie Madill437fa652016-05-03 15:13:24 -04002459 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002460 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002461 }
2462
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002463 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002464
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002465 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002466 {
Jamie Madill437fa652016-05-03 15:13:24 -04002467 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002468 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002469 }
2470
Jamie Madill45c785d2014-05-13 14:09:34 -04002471 return true;
2472}
2473
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002474bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2475{
2476 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002477 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002478 {
Jamie Madill437fa652016-05-03 15:13:24 -04002479 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002480 return false;
2481 }
2482
2483 return ValidateEndQueryBase(context, target);
2484}
2485
2486bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2487{
2488 if (!context->getExtensions().disjointTimerQuery)
2489 {
Jamie Madill437fa652016-05-03 15:13:24 -04002490 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002491 return false;
2492 }
2493
2494 if (target != GL_TIMESTAMP_EXT)
2495 {
Jamie Madill437fa652016-05-03 15:13:24 -04002496 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002497 return false;
2498 }
2499
2500 Query *queryObject = context->getQuery(id, true, target);
2501 if (queryObject == nullptr)
2502 {
Jamie Madill437fa652016-05-03 15:13:24 -04002503 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002504 return false;
2505 }
2506
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002507 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002508 {
Jamie Madill437fa652016-05-03 15:13:24 -04002509 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002510 return false;
2511 }
2512
2513 return true;
2514}
2515
Geoff Lang2186c382016-10-14 10:54:54 -04002516bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002517{
Geoff Lang2186c382016-10-14 10:54:54 -04002518 if (numParams)
2519 {
2520 *numParams = 0;
2521 }
2522
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002523 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2524 {
Jamie Madill437fa652016-05-03 15:13:24 -04002525 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002526 return false;
2527 }
2528
2529 switch (pname)
2530 {
2531 case GL_CURRENT_QUERY_EXT:
2532 if (target == GL_TIMESTAMP_EXT)
2533 {
Jamie Madill437fa652016-05-03 15:13:24 -04002534 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002535 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2536 return false;
2537 }
2538 break;
2539 case GL_QUERY_COUNTER_BITS_EXT:
2540 if (!context->getExtensions().disjointTimerQuery ||
2541 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2542 {
Jamie Madill437fa652016-05-03 15:13:24 -04002543 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002544 return false;
2545 }
2546 break;
2547 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002548 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002549 return false;
2550 }
2551
Geoff Lang2186c382016-10-14 10:54:54 -04002552 if (numParams)
2553 {
2554 // All queries return only one value
2555 *numParams = 1;
2556 }
2557
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002558 return true;
2559}
2560
2561bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2562{
2563 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002564 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002565 {
Jamie Madill437fa652016-05-03 15:13:24 -04002566 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002567 return false;
2568 }
2569
Geoff Lang2186c382016-10-14 10:54:54 -04002570 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002571}
2572
Geoff Lang2186c382016-10-14 10:54:54 -04002573bool ValidateGetQueryivRobustANGLE(Context *context,
2574 GLenum target,
2575 GLenum pname,
2576 GLsizei bufSize,
2577 GLsizei *length,
2578 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002579{
Geoff Lang2186c382016-10-14 10:54:54 -04002580 if (!ValidateRobustEntryPoint(context, bufSize))
2581 {
2582 return false;
2583 }
2584
2585 if (!ValidateGetQueryivBase(context, target, pname, length))
2586 {
2587 return false;
2588 }
2589
2590 if (!ValidateRobustBufferSize(context, bufSize, *length))
2591 {
2592 return false;
2593 }
2594
2595 return true;
2596}
2597
2598bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2599{
2600 if (numParams)
2601 {
2602 *numParams = 0;
2603 }
2604
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002605 Query *queryObject = context->getQuery(id, false, GL_NONE);
2606
2607 if (!queryObject)
2608 {
Jamie Madill437fa652016-05-03 15:13:24 -04002609 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002610 return false;
2611 }
2612
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002613 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002614 {
Jamie Madill437fa652016-05-03 15:13:24 -04002615 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002616 return false;
2617 }
2618
2619 switch (pname)
2620 {
2621 case GL_QUERY_RESULT_EXT:
2622 case GL_QUERY_RESULT_AVAILABLE_EXT:
2623 break;
2624
2625 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002626 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002627 return false;
2628 }
2629
Geoff Lang2186c382016-10-14 10:54:54 -04002630 if (numParams)
2631 {
2632 *numParams = 1;
2633 }
2634
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002635 return true;
2636}
2637
2638bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2639{
2640 if (!context->getExtensions().disjointTimerQuery)
2641 {
Jamie Madill437fa652016-05-03 15:13:24 -04002642 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002643 return false;
2644 }
Geoff Lang2186c382016-10-14 10:54:54 -04002645 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2646}
2647
2648bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2649 GLuint id,
2650 GLenum pname,
2651 GLsizei bufSize,
2652 GLsizei *length,
2653 GLint *params)
2654{
2655 if (!context->getExtensions().disjointTimerQuery)
2656 {
2657 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2658 return false;
2659 }
2660
2661 if (!ValidateRobustEntryPoint(context, bufSize))
2662 {
2663 return false;
2664 }
2665
2666 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2667 {
2668 return false;
2669 }
2670
2671 if (!ValidateRobustBufferSize(context, bufSize, *length))
2672 {
2673 return false;
2674 }
2675
2676 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002677}
2678
2679bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2680{
2681 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002682 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002683 {
Jamie Madill437fa652016-05-03 15:13:24 -04002684 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002685 return false;
2686 }
Geoff Lang2186c382016-10-14 10:54:54 -04002687 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2688}
2689
2690bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2691 GLuint id,
2692 GLenum pname,
2693 GLsizei bufSize,
2694 GLsizei *length,
2695 GLuint *params)
2696{
2697 if (!context->getExtensions().disjointTimerQuery &&
2698 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2699 {
2700 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2701 return false;
2702 }
2703
2704 if (!ValidateRobustEntryPoint(context, bufSize))
2705 {
2706 return false;
2707 }
2708
2709 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2710 {
2711 return false;
2712 }
2713
2714 if (!ValidateRobustBufferSize(context, bufSize, *length))
2715 {
2716 return false;
2717 }
2718
2719 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002720}
2721
2722bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2723{
2724 if (!context->getExtensions().disjointTimerQuery)
2725 {
Jamie Madill437fa652016-05-03 15:13:24 -04002726 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002727 return false;
2728 }
Geoff Lang2186c382016-10-14 10:54:54 -04002729 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2730}
2731
2732bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2733 GLuint id,
2734 GLenum pname,
2735 GLsizei bufSize,
2736 GLsizei *length,
2737 GLint64 *params)
2738{
2739 if (!context->getExtensions().disjointTimerQuery)
2740 {
2741 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2742 return false;
2743 }
2744
2745 if (!ValidateRobustEntryPoint(context, bufSize))
2746 {
2747 return false;
2748 }
2749
2750 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2751 {
2752 return false;
2753 }
2754
2755 if (!ValidateRobustBufferSize(context, bufSize, *length))
2756 {
2757 return false;
2758 }
2759
2760 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002761}
2762
2763bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2764{
2765 if (!context->getExtensions().disjointTimerQuery)
2766 {
Jamie Madill437fa652016-05-03 15:13:24 -04002767 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002768 return false;
2769 }
Geoff Lang2186c382016-10-14 10:54:54 -04002770 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2771}
2772
2773bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2774 GLuint id,
2775 GLenum pname,
2776 GLsizei bufSize,
2777 GLsizei *length,
2778 GLuint64 *params)
2779{
2780 if (!context->getExtensions().disjointTimerQuery)
2781 {
2782 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2783 return false;
2784 }
2785
2786 if (!ValidateRobustEntryPoint(context, bufSize))
2787 {
2788 return false;
2789 }
2790
2791 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2792 {
2793 return false;
2794 }
2795
2796 if (!ValidateRobustBufferSize(context, bufSize, *length))
2797 {
2798 return false;
2799 }
2800
2801 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002802}
2803
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002804bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002805 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002806 GLuint program,
2807 GLint location,
2808 GLsizei count)
2809{
2810 // Check for ES31 program uniform entry points
2811 if (context->getClientVersion() < Version(3, 1))
2812 {
2813 context->handleError(Error(GL_INVALID_OPERATION));
2814 return false;
2815 }
2816
2817 const LinkedUniform *uniform = nullptr;
2818 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002819 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2820 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002821}
2822
Frank Henigmana98a6472017-02-02 21:38:32 -05002823bool ValidateProgramUniform1iv(gl::Context *context,
2824 GLuint program,
2825 GLint location,
2826 GLsizei count,
2827 const GLint *value)
2828{
2829 // Check for ES31 program uniform entry points
2830 if (context->getClientVersion() < Version(3, 1))
2831 {
2832 context->handleError(Error(GL_INVALID_OPERATION));
2833 return false;
2834 }
2835
2836 const LinkedUniform *uniform = nullptr;
2837 gl::Program *programObject = GetValidProgram(context, program);
2838 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2839 ValidateUniform1ivValue(context, uniform->type, count, value);
2840}
2841
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002842bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002843 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002844 GLuint program,
2845 GLint location,
2846 GLsizei count,
2847 GLboolean transpose)
2848{
2849 // Check for ES31 program uniform entry points
2850 if (context->getClientVersion() < Version(3, 1))
2851 {
2852 context->handleError(Error(GL_INVALID_OPERATION));
2853 return false;
2854 }
2855
2856 const LinkedUniform *uniform = nullptr;
2857 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002858 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2859 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002860}
2861
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002862bool ValidateUniform(gl::Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002863{
2864 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002865 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002866 {
Jamie Madill437fa652016-05-03 15:13:24 -04002867 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002868 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002869 }
2870
Jamie Madill62d31cb2015-09-11 13:25:51 -04002871 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002872 gl::Program *programObject = context->getGLState().getProgram();
2873 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2874 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002875}
2876
Frank Henigmana98a6472017-02-02 21:38:32 -05002877bool ValidateUniform1iv(gl::Context *context, GLint location, GLsizei count, const GLint *value)
2878{
2879 const LinkedUniform *uniform = nullptr;
2880 gl::Program *programObject = context->getGLState().getProgram();
2881 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2882 ValidateUniform1ivValue(context, uniform->type, count, value);
2883}
2884
He Yunchaoced53ae2016-11-29 15:00:51 +08002885bool ValidateUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002886 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002887 GLint location,
2888 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002889 GLboolean transpose)
2890{
2891 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002892 int rows = VariableRowCount(valueType);
2893 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002894 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002895 {
Jamie Madill437fa652016-05-03 15:13:24 -04002896 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002897 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002898 }
2899
Martin Radev1be913c2016-07-11 17:59:16 +03002900 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002901 {
Jamie Madill437fa652016-05-03 15:13:24 -04002902 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002903 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002904 }
2905
Jamie Madill62d31cb2015-09-11 13:25:51 -04002906 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002907 gl::Program *programObject = context->getGLState().getProgram();
2908 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2909 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002910}
2911
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002912bool ValidateStateQuery(ValidationContext *context,
2913 GLenum pname,
2914 GLenum *nativeType,
2915 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002916{
2917 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2918 {
Jamie Madill437fa652016-05-03 15:13:24 -04002919 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002920 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002921 }
2922
Jamie Madill0af26e12015-03-05 19:54:33 -05002923 const Caps &caps = context->getCaps();
2924
Jamie Madill893ab082014-05-16 16:56:10 -04002925 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2926 {
2927 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2928
Jamie Madill0af26e12015-03-05 19:54:33 -05002929 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002930 {
Jamie Madill437fa652016-05-03 15:13:24 -04002931 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002932 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002933 }
2934 }
2935
2936 switch (pname)
2937 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002938 case GL_TEXTURE_BINDING_2D:
2939 case GL_TEXTURE_BINDING_CUBE_MAP:
2940 case GL_TEXTURE_BINDING_3D:
2941 case GL_TEXTURE_BINDING_2D_ARRAY:
2942 break;
2943 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2944 if (!context->getExtensions().eglStreamConsumerExternal &&
2945 !context->getExtensions().eglImageExternal)
2946 {
2947 context->handleError(Error(GL_INVALID_ENUM,
2948 "Neither NV_EGL_stream_consumer_external nor "
2949 "GL_OES_EGL_image_external extensions enabled"));
2950 return false;
2951 }
2952 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002953
He Yunchaoced53ae2016-11-29 15:00:51 +08002954 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2955 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002956 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002957 if (context->getGLState().getReadFramebuffer()->checkStatus(
2958 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002959 {
Jamie Madill437fa652016-05-03 15:13:24 -04002960 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002961 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002962 }
2963
Jamie Madill51f40ec2016-06-15 14:06:00 -04002964 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2965 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002966
2967 if (framebuffer->getReadBufferState() == GL_NONE)
2968 {
2969 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2970 return false;
2971 }
2972
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002973 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002974 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002975 {
Jamie Madill437fa652016-05-03 15:13:24 -04002976 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002977 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002978 }
2979 }
2980 break;
2981
He Yunchaoced53ae2016-11-29 15:00:51 +08002982 default:
2983 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002984 }
2985
2986 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002987 if (*numParams == 0)
2988 {
2989 return false;
2990 }
2991
2992 return true;
2993}
2994
2995bool ValidateRobustStateQuery(ValidationContext *context,
2996 GLenum pname,
2997 GLsizei bufSize,
2998 GLenum *nativeType,
2999 unsigned int *numParams)
3000{
3001 if (!ValidateRobustEntryPoint(context, bufSize))
3002 {
3003 return false;
3004 }
3005
3006 if (!ValidateStateQuery(context, pname, nativeType, numParams))
3007 {
3008 return false;
3009 }
3010
3011 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04003012 {
3013 return false;
3014 }
3015
3016 return true;
3017}
3018
Jamie Madillc29968b2016-01-20 11:17:23 -05003019bool ValidateCopyTexImageParametersBase(ValidationContext *context,
3020 GLenum target,
3021 GLint level,
3022 GLenum internalformat,
3023 bool isSubImage,
3024 GLint xoffset,
3025 GLint yoffset,
3026 GLint zoffset,
3027 GLint x,
3028 GLint y,
3029 GLsizei width,
3030 GLsizei height,
3031 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04003032 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04003033{
Jamie Madill560a8d82014-05-21 13:06:20 -04003034 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
3035 {
Jamie Madill437fa652016-05-03 15:13:24 -04003036 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003037 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003038 }
3039
He Yunchaoced53ae2016-11-29 15:00:51 +08003040 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3041 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04003042 {
Jamie Madill437fa652016-05-03 15:13:24 -04003043 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003044 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003045 }
3046
3047 if (border != 0)
3048 {
Jamie Madill437fa652016-05-03 15:13:24 -04003049 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003050 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003051 }
3052
3053 if (!ValidMipLevel(context, target, level))
3054 {
Jamie Madill437fa652016-05-03 15:13:24 -04003055 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003056 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003057 }
3058
Jamie Madill51f40ec2016-06-15 14:06:00 -04003059 const auto &state = context->getGLState();
3060 auto readFramebuffer = state.getReadFramebuffer();
3061 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003062 {
Jamie Madill437fa652016-05-03 15:13:24 -04003063 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003064 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003065 }
3066
Jamie Madill51f40ec2016-06-15 14:06:00 -04003067 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003068 {
Jamie Madill437fa652016-05-03 15:13:24 -04003069 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003070 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003071 }
3072
Martin Radev138064f2016-07-15 12:03:41 +03003073 if (readFramebuffer->getReadBufferState() == GL_NONE)
3074 {
3075 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3076 return false;
3077 }
3078
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003079 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3080 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003081 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003082 // situation is an application error that would lead to a crash in ANGLE.
3083 if (readFramebuffer->getReadColorbuffer() == nullptr)
3084 {
3085 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3086 return false;
3087 }
3088
Geoff Langaae65a42014-05-26 12:43:44 -04003089 const gl::Caps &caps = context->getCaps();
3090
Geoff Langaae65a42014-05-26 12:43:44 -04003091 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003092 switch (target)
3093 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003094 case GL_TEXTURE_2D:
3095 maxDimension = caps.max2DTextureSize;
3096 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003097
He Yunchaoced53ae2016-11-29 15:00:51 +08003098 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3099 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3100 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3101 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3102 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3103 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3104 maxDimension = caps.maxCubeMapTextureSize;
3105 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003106
He Yunchaoced53ae2016-11-29 15:00:51 +08003107 case GL_TEXTURE_2D_ARRAY:
3108 maxDimension = caps.max2DTextureSize;
3109 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003110
He Yunchaoced53ae2016-11-29 15:00:51 +08003111 case GL_TEXTURE_3D:
3112 maxDimension = caps.max3DTextureSize;
3113 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003114
He Yunchaoced53ae2016-11-29 15:00:51 +08003115 default:
3116 context->handleError(Error(GL_INVALID_ENUM));
3117 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003118 }
3119
Jamie Madillc29968b2016-01-20 11:17:23 -05003120 gl::Texture *texture =
3121 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003122 if (!texture)
3123 {
Jamie Madill437fa652016-05-03 15:13:24 -04003124 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003125 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003126 }
3127
Geoff Lang69cce582015-09-17 13:20:36 -04003128 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003129 {
Jamie Madill437fa652016-05-03 15:13:24 -04003130 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003131 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003132 }
3133
Geoff Lang5d601382014-07-22 15:14:06 -04003134 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3135
3136 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003137 {
Jamie Madill437fa652016-05-03 15:13:24 -04003138 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003139 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003140 }
3141
Geoff Lang44ff5a72017-02-03 15:15:43 -05003142 if (formatInfo.compressed &&
3143 !ValidCompressedImageSize(context, internalformat, xoffset, yoffset, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003144 {
Jamie Madill437fa652016-05-03 15:13:24 -04003145 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003146 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003147 }
3148
3149 if (isSubImage)
3150 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003151 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3152 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3153 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003154 {
Jamie Madill437fa652016-05-03 15:13:24 -04003155 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003156 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003157 }
3158 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003159 else
3160 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003161 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003162 {
Jamie Madill437fa652016-05-03 15:13:24 -04003163 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003164 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003165 }
3166
Geoff Langeb66a6e2016-10-31 13:06:12 -04003167 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003168 {
Jamie Madill437fa652016-05-03 15:13:24 -04003169 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003170 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003171 }
3172
3173 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003174 if (static_cast<int>(width) > maxLevelDimension ||
3175 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003176 {
Jamie Madill437fa652016-05-03 15:13:24 -04003177 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003178 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003179 }
3180 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003181
Jamie Madill0c8abca2016-07-22 20:21:26 -04003182 if (textureFormatOut)
3183 {
3184 *textureFormatOut = texture->getFormat(target, level);
3185 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003186
3187 // Detect texture copying feedback loops for WebGL.
3188 if (context->getExtensions().webglCompatibility)
3189 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05003190 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05003191 {
3192 context->handleError(Error(GL_INVALID_OPERATION,
3193 "Texture copying feedback loop formed between Framebuffer "
3194 "and specified Texture level."));
3195 return false;
3196 }
3197 }
3198
Jamie Madill560a8d82014-05-21 13:06:20 -04003199 return true;
3200}
3201
Jiajia Qind9671222016-11-29 16:30:31 +08003202bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003203{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003204 switch (mode)
3205 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003206 case GL_POINTS:
3207 case GL_LINES:
3208 case GL_LINE_LOOP:
3209 case GL_LINE_STRIP:
3210 case GL_TRIANGLES:
3211 case GL_TRIANGLE_STRIP:
3212 case GL_TRIANGLE_FAN:
3213 break;
3214 default:
3215 context->handleError(Error(GL_INVALID_ENUM));
3216 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003217 }
3218
Jamie Madill250d33f2014-06-06 17:09:03 -04003219 if (count < 0)
3220 {
Jamie Madill437fa652016-05-03 15:13:24 -04003221 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003222 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003223 }
3224
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003225 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003226
Jamie Madill250d33f2014-06-06 17:09:03 -04003227 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003228 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003229 {
Jamie Madill437fa652016-05-03 15:13:24 -04003230 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003231 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003232 }
3233
Jamie Madillcbcde722017-01-06 14:50:00 -05003234 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3235 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003236 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003237 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3238 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003239 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003240 const FramebufferAttachment *dsAttachment =
3241 framebuffer->getStencilOrDepthStencilAttachment();
3242 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003243 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003244 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003245
3246 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3247 bool differentWritemasks =
3248 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3249 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3250 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3251 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3252
3253 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003254 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003255 if (!context->getExtensions().webglCompatibility)
3256 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003257 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3258 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003259 }
Jamie Madill437fa652016-05-03 15:13:24 -04003260 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003261 return false;
3262 }
Jamie Madillac528012014-06-20 13:21:23 -04003263 }
3264
Jamie Madill51f40ec2016-06-15 14:06:00 -04003265 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003266 {
Jamie Madill437fa652016-05-03 15:13:24 -04003267 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003268 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003269 }
3270
Geoff Lang7dd2e102014-11-10 15:19:26 -05003271 gl::Program *program = state.getProgram();
3272 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003273 {
Jamie Madill437fa652016-05-03 15:13:24 -04003274 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003275 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003276 }
3277
Geoff Lang7dd2e102014-11-10 15:19:26 -05003278 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003279 {
Jamie Madill437fa652016-05-03 15:13:24 -04003280 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003281 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003282 }
3283
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003284 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003285 for (unsigned int uniformBlockIndex = 0;
3286 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003287 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003288 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003289 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003290 const OffsetBindingPointer<Buffer> &uniformBuffer =
3291 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003292
Geoff Lang5d124a62015-09-15 13:03:27 -04003293 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003294 {
3295 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003296 context->handleError(
3297 Error(GL_INVALID_OPERATION,
3298 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003299 return false;
3300 }
3301
Geoff Lang5d124a62015-09-15 13:03:27 -04003302 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003303 if (uniformBufferSize == 0)
3304 {
3305 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003306 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003307 }
3308
Jamie Madill62d31cb2015-09-11 13:25:51 -04003309 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003310 {
3311 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003312 context->handleError(
3313 Error(GL_INVALID_OPERATION,
3314 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003315 return false;
3316 }
3317 }
3318
Jamie Madilla4595b82017-01-11 17:36:34 -05003319 // Detect rendering feedback loops for WebGL.
3320 if (context->getExtensions().webglCompatibility)
3321 {
3322 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3323 {
3324 context->handleError(
3325 Error(GL_INVALID_OPERATION,
3326 "Rendering feedback loop formed between Framebuffer and active Texture."));
3327 return false;
3328 }
3329 }
3330
Jamie Madill250d33f2014-06-06 17:09:03 -04003331 // No-op if zero count
3332 return (count > 0);
3333}
3334
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003335bool ValidateDrawArrays(ValidationContext *context,
3336 GLenum mode,
3337 GLint first,
3338 GLsizei count,
3339 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003340{
Jamie Madillfd716582014-06-06 17:09:04 -04003341 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003342 {
Jamie Madill437fa652016-05-03 15:13:24 -04003343 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003344 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003345 }
3346
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003347 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003348 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003349 if (curTransformFeedback && curTransformFeedback->isActive() &&
3350 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003351 {
3352 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003353 // that does not match the current transform feedback object's draw mode (if transform
3354 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003355 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003356 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003357 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003358 }
3359
Jiajia Qind9671222016-11-29 16:30:31 +08003360 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003361 {
3362 return false;
3363 }
3364
Corentin Wallez71168a02016-12-19 15:11:18 -08003365 // Check the computation of maxVertex doesn't overflow.
3366 // - first < 0 or count < 0 have been checked as an error condition
3367 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3368 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3369 ASSERT(count > 0 && first >= 0);
3370 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3371 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003372 {
3373 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3374 return false;
3375 }
3376
Corentin Wallez71168a02016-12-19 15:11:18 -08003377 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003378 {
3379 return false;
3380 }
3381
3382 return true;
3383}
3384
He Yunchaoced53ae2016-11-29 15:00:51 +08003385bool ValidateDrawArraysInstanced(Context *context,
3386 GLenum mode,
3387 GLint first,
3388 GLsizei count,
3389 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003390{
3391 if (primcount < 0)
3392 {
Jamie Madill437fa652016-05-03 15:13:24 -04003393 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003394 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003395 }
3396
Jamie Madill2b976812014-08-25 15:47:49 -04003397 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003398 {
3399 return false;
3400 }
3401
3402 // No-op if zero primitive count
3403 return (primcount > 0);
3404}
3405
Geoff Lang87a93302014-09-16 13:29:43 -04003406static bool ValidateDrawInstancedANGLE(Context *context)
3407{
3408 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003409 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003410
Geoff Lang7dd2e102014-11-10 15:19:26 -05003411 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003412
Jiawei-Shao2597fb62016-12-09 16:38:02 +08003413 const auto &attribs = state.getVertexArray()->getVertexAttributes();
3414 const auto &bindings = state.getVertexArray()->getVertexBindings();
Jamie Madill63805b42015-08-25 13:17:39 -04003415 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003416 {
Jiawei-Shao2597fb62016-12-09 16:38:02 +08003417 const VertexAttribute &attrib = attribs[attributeIndex];
3418 const VertexBinding &binding = bindings[attrib.bindingIndex];
3419 if (program->isAttribLocationActive(attributeIndex) && binding.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003420 {
3421 return true;
3422 }
3423 }
3424
Jamie Madill437fa652016-05-03 15:13:24 -04003425 context->handleError(Error(GL_INVALID_OPERATION,
3426 "ANGLE_instanced_arrays requires that at least one active attribute"
3427 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003428 return false;
3429}
3430
He Yunchaoced53ae2016-11-29 15:00:51 +08003431bool ValidateDrawArraysInstancedANGLE(Context *context,
3432 GLenum mode,
3433 GLint first,
3434 GLsizei count,
3435 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003436{
3437 if (!ValidateDrawInstancedANGLE(context))
3438 {
3439 return false;
3440 }
3441
3442 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3443}
3444
Jiajia Qind9671222016-11-29 16:30:31 +08003445bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003446{
Jamie Madill250d33f2014-06-06 17:09:03 -04003447 switch (type)
3448 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003449 case GL_UNSIGNED_BYTE:
3450 case GL_UNSIGNED_SHORT:
3451 break;
3452 case GL_UNSIGNED_INT:
3453 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3454 {
3455 context->handleError(Error(GL_INVALID_ENUM));
3456 return false;
3457 }
3458 break;
3459 default:
3460 context->handleError(Error(GL_INVALID_ENUM));
3461 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003462 }
3463
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003464 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003465
3466 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003467 if (curTransformFeedback && curTransformFeedback->isActive() &&
3468 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003469 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003470 // It is an invalid operation to call DrawElements, DrawRangeElements or
3471 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003472 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003473 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003474 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003475 }
3476
Jiajia Qind9671222016-11-29 16:30:31 +08003477 return true;
3478}
3479
3480bool ValidateDrawElements(ValidationContext *context,
3481 GLenum mode,
3482 GLsizei count,
3483 GLenum type,
3484 const GLvoid *indices,
3485 GLsizei primcount,
3486 IndexRange *indexRangeOut)
3487{
3488 if (!ValidateDrawElementsBase(context, type))
3489 return false;
3490
3491 const State &state = context->getGLState();
3492
Jamie Madill250d33f2014-06-06 17:09:03 -04003493 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003494 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003495 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003496 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04003497 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003498 }
3499
He Yunchaoced53ae2016-11-29 15:00:51 +08003500 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003501 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003502
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003503 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3504
3505 if (context->getExtensions().webglCompatibility)
3506 {
3507 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3508 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3509 {
3510 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3511 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3512 // data type passed to the call, or an INVALID_OPERATION error is generated.
3513 context->handleError(Error(GL_INVALID_OPERATION,
3514 "indices must be a multiple of the element type size."));
3515 return false;
3516 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003517
3518 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3519 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3520 // error is generated.
3521 if (reinterpret_cast<intptr_t>(indices) < 0)
3522 {
3523 context->handleError(Error(GL_INVALID_VALUE, "Offset < 0."));
3524 return false;
3525 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003526 }
3527
3528 if (context->getExtensions().webglCompatibility ||
3529 !context->getGLState().areClientArraysEnabled())
3530 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003531 if (!elementArrayBuffer && count > 0)
3532 {
3533 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3534 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3535 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3536 context->handleError(Error(GL_INVALID_OPERATION,
3537 "There is no element array buffer bound and count > 0."));
3538 return false;
3539 }
3540 }
3541
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003542 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003543 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003544 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003545 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003546 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3547 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3548 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3549 constexpr uint64_t kMaxTypeSize = 8;
3550 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3551 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3552 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003553
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003554 uint64_t typeSize = typeBytes;
3555 uint64_t elementCount = static_cast<uint64_t>(count);
3556 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3557
3558 // Doing the multiplication here is overflow-safe
3559 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3560
3561 // The offset can be any value, check for overflows
3562 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3563 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003564 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003565 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003566 return false;
3567 }
3568
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003569 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3570 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003571 {
3572 context->handleError(
3573 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
3574 return false;
3575 }
3576 }
3577 else if (!indices)
3578 {
3579 // This is an application error that would normally result in a crash,
3580 // but we catch it and return an error
3581 context->handleError(
3582 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003583 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003584 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003585 }
3586
Jiajia Qind9671222016-11-29 16:30:31 +08003587 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003588 {
3589 return false;
3590 }
3591
Jamie Madill2b976812014-08-25 15:47:49 -04003592 // Use max index to validate if our vertex buffers are large enough for the pull.
3593 // TODO: offer fast path, with disabled index validation.
3594 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3595 if (elementArrayBuffer)
3596 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003597 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003598 Error error =
3599 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3600 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003601 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003602 {
Jamie Madill437fa652016-05-03 15:13:24 -04003603 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003604 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003605 }
3606 }
3607 else
3608 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003609 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003610 }
3611
Jamie Madille79b1e12015-11-04 16:36:37 -05003612 // If we use an index greater than our maximum supported index range, return an error.
3613 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3614 // return an error if possible here.
3615 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3616 {
Jamie Madill437fa652016-05-03 15:13:24 -04003617 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003618 return false;
3619 }
3620
Corentin Wallez92db6942016-12-09 13:10:36 -05003621 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3622 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003623 {
3624 return false;
3625 }
3626
Geoff Lang3edfe032015-09-04 16:38:24 -04003627 // No op if there are no real indices in the index data (all are primitive restart).
3628 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003629}
3630
Geoff Langb1196682014-07-23 13:47:29 -04003631bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003632 GLenum mode,
3633 GLsizei count,
3634 GLenum type,
3635 const GLvoid *indices,
3636 GLsizei primcount,
3637 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003638{
3639 if (primcount < 0)
3640 {
Jamie Madill437fa652016-05-03 15:13:24 -04003641 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003642 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003643 }
3644
Jamie Madill2b976812014-08-25 15:47:49 -04003645 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003646 {
3647 return false;
3648 }
3649
3650 // No-op zero primitive count
3651 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003652}
3653
Geoff Lang3edfe032015-09-04 16:38:24 -04003654bool ValidateDrawElementsInstancedANGLE(Context *context,
3655 GLenum mode,
3656 GLsizei count,
3657 GLenum type,
3658 const GLvoid *indices,
3659 GLsizei primcount,
3660 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003661{
3662 if (!ValidateDrawInstancedANGLE(context))
3663 {
3664 return false;
3665 }
3666
He Yunchaoced53ae2016-11-29 15:00:51 +08003667 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3668 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003669}
3670
He Yunchaoced53ae2016-11-29 15:00:51 +08003671bool ValidateFramebufferTextureBase(Context *context,
3672 GLenum target,
3673 GLenum attachment,
3674 GLuint texture,
3675 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003676{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003677 if (!ValidFramebufferTarget(target))
3678 {
Jamie Madill437fa652016-05-03 15:13:24 -04003679 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003680 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003681 }
3682
3683 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003684 {
3685 return false;
3686 }
3687
Jamie Madill55ec3b12014-07-03 10:38:57 -04003688 if (texture != 0)
3689 {
3690 gl::Texture *tex = context->getTexture(texture);
3691
3692 if (tex == NULL)
3693 {
Jamie Madill437fa652016-05-03 15:13:24 -04003694 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003695 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003696 }
3697
3698 if (level < 0)
3699 {
Jamie Madill437fa652016-05-03 15:13:24 -04003700 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003701 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003702 }
3703 }
3704
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003705 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003706 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003707
Jamie Madill84115c92015-04-23 15:00:07 -04003708 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003709 {
Jamie Madill437fa652016-05-03 15:13:24 -04003710 context->handleError(
3711 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003712 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003713 }
3714
3715 return true;
3716}
3717
He Yunchaoced53ae2016-11-29 15:00:51 +08003718bool ValidateFramebufferTexture2D(Context *context,
3719 GLenum target,
3720 GLenum attachment,
3721 GLenum textarget,
3722 GLuint texture,
3723 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003724{
He Yunchaoced53ae2016-11-29 15:00:51 +08003725 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3726 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003727 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3728 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003729 {
Jamie Madill437fa652016-05-03 15:13:24 -04003730 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003731 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003732 }
3733
3734 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003735 {
3736 return false;
3737 }
3738
Jamie Madill55ec3b12014-07-03 10:38:57 -04003739 if (texture != 0)
3740 {
3741 gl::Texture *tex = context->getTexture(texture);
3742 ASSERT(tex);
3743
Jamie Madill2a6564e2014-07-11 09:53:19 -04003744 const gl::Caps &caps = context->getCaps();
3745
Jamie Madill55ec3b12014-07-03 10:38:57 -04003746 switch (textarget)
3747 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003748 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003749 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003750 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003751 {
Jamie Madill437fa652016-05-03 15:13:24 -04003752 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003753 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003754 }
3755 if (tex->getTarget() != GL_TEXTURE_2D)
3756 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003757 context->handleError(Error(GL_INVALID_OPERATION,
3758 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003759 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003760 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003761 }
3762 break;
3763
He Yunchaoced53ae2016-11-29 15:00:51 +08003764 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3765 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3766 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3767 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3768 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3769 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003770 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003771 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003772 {
Jamie Madill437fa652016-05-03 15:13:24 -04003773 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003774 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003775 }
3776 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3777 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003778 context->handleError(Error(GL_INVALID_OPERATION,
3779 "Textarget must match the texture target type."));
3780 return false;
3781 }
3782 }
3783 break;
3784
3785 case GL_TEXTURE_2D_MULTISAMPLE:
3786 {
3787 if (context->getClientVersion() < ES_3_1)
3788 {
3789 context->handleError(Error(GL_INVALID_OPERATION,
3790 "Texture target requires at least OpenGL ES 3.1."));
3791 return false;
3792 }
3793
3794 if (level != 0)
3795 {
3796 context->handleError(
3797 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
3798 return false;
3799 }
3800 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
3801 {
3802 context->handleError(Error(GL_INVALID_OPERATION,
3803 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003804 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003805 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003806 }
3807 break;
3808
He Yunchaoced53ae2016-11-29 15:00:51 +08003809 default:
3810 context->handleError(Error(GL_INVALID_ENUM));
3811 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003812 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003813
Jamie Madilla3944d42016-07-22 22:13:26 -04003814 const Format &format = tex->getFormat(textarget, level);
3815 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003816 {
Jamie Madill437fa652016-05-03 15:13:24 -04003817 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003818 return false;
3819 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003820 }
3821
Jamie Madill570f7c82014-07-03 10:38:54 -04003822 return true;
3823}
3824
Geoff Langb1196682014-07-23 13:47:29 -04003825bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003826{
3827 if (program == 0)
3828 {
Jamie Madill437fa652016-05-03 15:13:24 -04003829 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003830 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003831 }
3832
Dian Xiang769769a2015-09-09 15:20:08 -07003833 gl::Program *programObject = GetValidProgram(context, program);
3834 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003835 {
3836 return false;
3837 }
3838
Jamie Madill0063c512014-08-25 15:47:53 -04003839 if (!programObject || !programObject->isLinked())
3840 {
Jamie Madill437fa652016-05-03 15:13:24 -04003841 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003842 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003843 }
3844
Geoff Lang7dd2e102014-11-10 15:19:26 -05003845 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003846 {
Jamie Madill437fa652016-05-03 15:13:24 -04003847 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003848 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003849 }
3850
Jamie Madill0063c512014-08-25 15:47:53 -04003851 return true;
3852}
3853
He Yunchaoced53ae2016-11-29 15:00:51 +08003854bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003855{
3856 return ValidateGetUniformBase(context, program, location);
3857}
3858
He Yunchaoced53ae2016-11-29 15:00:51 +08003859bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003860{
Jamie Madill78f41802014-08-25 15:47:55 -04003861 return ValidateGetUniformBase(context, program, location);
3862}
3863
Geoff Langf41d0ee2016-10-07 13:04:23 -04003864static bool ValidateSizedGetUniform(Context *context,
3865 GLuint program,
3866 GLint location,
3867 GLsizei bufSize,
3868 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003869{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003870 if (length)
3871 {
3872 *length = 0;
3873 }
3874
Jamie Madill78f41802014-08-25 15:47:55 -04003875 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003876 {
Jamie Madill78f41802014-08-25 15:47:55 -04003877 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003878 }
3879
Geoff Langf41d0ee2016-10-07 13:04:23 -04003880 if (bufSize < 0)
3881 {
3882 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3883 return false;
3884 }
3885
Jamie Madilla502c742014-08-28 17:19:13 -04003886 gl::Program *programObject = context->getProgram(program);
3887 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003888
Jamie Madill78f41802014-08-25 15:47:55 -04003889 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003890 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003891 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003892 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003893 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003894 context->handleError(
3895 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003896 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003897 }
3898
Geoff Langf41d0ee2016-10-07 13:04:23 -04003899 if (length)
3900 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003901 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003902 }
3903
Jamie Madill0063c512014-08-25 15:47:53 -04003904 return true;
3905}
3906
He Yunchaoced53ae2016-11-29 15:00:51 +08003907bool ValidateGetnUniformfvEXT(Context *context,
3908 GLuint program,
3909 GLint location,
3910 GLsizei bufSize,
3911 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003912{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003913 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003914}
3915
He Yunchaoced53ae2016-11-29 15:00:51 +08003916bool ValidateGetnUniformivEXT(Context *context,
3917 GLuint program,
3918 GLint location,
3919 GLsizei bufSize,
3920 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003921{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003922 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3923}
3924
3925bool ValidateGetUniformfvRobustANGLE(Context *context,
3926 GLuint program,
3927 GLint location,
3928 GLsizei bufSize,
3929 GLsizei *length,
3930 GLfloat *params)
3931{
3932 if (!ValidateRobustEntryPoint(context, bufSize))
3933 {
3934 return false;
3935 }
3936
3937 // bufSize is validated in ValidateSizedGetUniform
3938 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3939}
3940
3941bool ValidateGetUniformivRobustANGLE(Context *context,
3942 GLuint program,
3943 GLint location,
3944 GLsizei bufSize,
3945 GLsizei *length,
3946 GLint *params)
3947{
3948 if (!ValidateRobustEntryPoint(context, bufSize))
3949 {
3950 return false;
3951 }
3952
3953 // bufSize is validated in ValidateSizedGetUniform
3954 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3955}
3956
3957bool ValidateGetUniformuivRobustANGLE(Context *context,
3958 GLuint program,
3959 GLint location,
3960 GLsizei bufSize,
3961 GLsizei *length,
3962 GLuint *params)
3963{
3964 if (!ValidateRobustEntryPoint(context, bufSize))
3965 {
3966 return false;
3967 }
3968
3969 if (context->getClientMajorVersion() < 3)
3970 {
3971 context->handleError(
3972 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3973 return false;
3974 }
3975
3976 // bufSize is validated in ValidateSizedGetUniform
3977 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003978}
3979
He Yunchaoced53ae2016-11-29 15:00:51 +08003980bool ValidateDiscardFramebufferBase(Context *context,
3981 GLenum target,
3982 GLsizei numAttachments,
3983 const GLenum *attachments,
3984 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003985{
3986 if (numAttachments < 0)
3987 {
Jamie Madill437fa652016-05-03 15:13:24 -04003988 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003989 return false;
3990 }
3991
3992 for (GLsizei i = 0; i < numAttachments; ++i)
3993 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003994 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003995 {
3996 if (defaultFramebuffer)
3997 {
Jamie Madill437fa652016-05-03 15:13:24 -04003998 context->handleError(Error(
3999 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07004000 return false;
4001 }
4002
4003 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
4004 {
Jamie Madill437fa652016-05-03 15:13:24 -04004005 context->handleError(Error(GL_INVALID_OPERATION,
4006 "Requested color attachment is greater than the maximum "
4007 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07004008 return false;
4009 }
4010 }
4011 else
4012 {
4013 switch (attachments[i])
4014 {
He Yunchaoced53ae2016-11-29 15:00:51 +08004015 case GL_DEPTH_ATTACHMENT:
4016 case GL_STENCIL_ATTACHMENT:
4017 case GL_DEPTH_STENCIL_ATTACHMENT:
4018 if (defaultFramebuffer)
4019 {
4020 context->handleError(
4021 Error(GL_INVALID_ENUM,
4022 "Invalid attachment when the default framebuffer is bound"));
4023 return false;
4024 }
4025 break;
4026 case GL_COLOR:
4027 case GL_DEPTH:
4028 case GL_STENCIL:
4029 if (!defaultFramebuffer)
4030 {
4031 context->handleError(
4032 Error(GL_INVALID_ENUM,
4033 "Invalid attachment when the default framebuffer is not bound"));
4034 return false;
4035 }
4036 break;
4037 default:
4038 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07004039 return false;
Austin Kinross08332632015-05-05 13:35:47 -07004040 }
4041 }
4042 }
4043
4044 return true;
4045}
4046
Austin Kinross6ee1e782015-05-29 17:05:37 -07004047bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
4048{
4049 // Note that debug marker calls must not set error state
4050
4051 if (length < 0)
4052 {
4053 return false;
4054 }
4055
4056 if (marker == nullptr)
4057 {
4058 return false;
4059 }
4060
4061 return true;
4062}
4063
4064bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
4065{
4066 // Note that debug marker calls must not set error state
4067
4068 if (length < 0)
4069 {
4070 return false;
4071 }
4072
4073 if (length > 0 && marker == nullptr)
4074 {
4075 return false;
4076 }
4077
4078 return true;
4079}
4080
Geoff Langdcab33b2015-07-21 13:03:16 -04004081bool ValidateEGLImageTargetTexture2DOES(Context *context,
4082 egl::Display *display,
4083 GLenum target,
4084 egl::Image *image)
4085{
Geoff Langa8406172015-07-21 16:53:39 -04004086 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4087 {
Jamie Madill437fa652016-05-03 15:13:24 -04004088 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004089 return false;
4090 }
4091
4092 switch (target)
4093 {
4094 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004095 if (!context->getExtensions().eglImage)
4096 {
4097 context->handleError(Error(
4098 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4099 }
4100 break;
4101
4102 case GL_TEXTURE_EXTERNAL_OES:
4103 if (!context->getExtensions().eglImageExternal)
4104 {
4105 context->handleError(Error(
4106 GL_INVALID_ENUM,
4107 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4108 }
Geoff Langa8406172015-07-21 16:53:39 -04004109 break;
4110
4111 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004112 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004113 return false;
4114 }
4115
4116 if (!display->isValidImage(image))
4117 {
Jamie Madill437fa652016-05-03 15:13:24 -04004118 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004119 return false;
4120 }
4121
4122 if (image->getSamples() > 0)
4123 {
Jamie Madill437fa652016-05-03 15:13:24 -04004124 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004125 "cannot create a 2D texture from a multisampled EGL image."));
4126 return false;
4127 }
4128
Jamie Madilla3944d42016-07-22 22:13:26 -04004129 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004130 if (!textureCaps.texturable)
4131 {
Jamie Madill437fa652016-05-03 15:13:24 -04004132 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004133 "EGL image internal format is not supported as a texture."));
4134 return false;
4135 }
4136
Geoff Langdcab33b2015-07-21 13:03:16 -04004137 return true;
4138}
4139
4140bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4141 egl::Display *display,
4142 GLenum target,
4143 egl::Image *image)
4144{
Geoff Langa8406172015-07-21 16:53:39 -04004145 if (!context->getExtensions().eglImage)
4146 {
Jamie Madill437fa652016-05-03 15:13:24 -04004147 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004148 return false;
4149 }
4150
4151 switch (target)
4152 {
4153 case GL_RENDERBUFFER:
4154 break;
4155
4156 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004157 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004158 return false;
4159 }
4160
4161 if (!display->isValidImage(image))
4162 {
Jamie Madill437fa652016-05-03 15:13:24 -04004163 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004164 return false;
4165 }
4166
Jamie Madilla3944d42016-07-22 22:13:26 -04004167 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004168 if (!textureCaps.renderable)
4169 {
Jamie Madill437fa652016-05-03 15:13:24 -04004170 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004171 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4172 return false;
4173 }
4174
Geoff Langdcab33b2015-07-21 13:03:16 -04004175 return true;
4176}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004177
4178bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4179{
Geoff Lang36167ab2015-12-07 10:27:14 -05004180 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004181 {
4182 // The default VAO should always exist
4183 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004184 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004185 return false;
4186 }
4187
4188 return true;
4189}
4190
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004191bool ValidateLinkProgram(Context *context, GLuint program)
4192{
4193 if (context->hasActiveTransformFeedback(program))
4194 {
4195 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004196 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004197 "Cannot link program while program is associated with an active "
4198 "transform feedback object."));
4199 return false;
4200 }
4201 return true;
4202}
4203
Geoff Langc5629752015-12-07 16:29:04 -05004204bool ValidateProgramBinaryBase(Context *context,
4205 GLuint program,
4206 GLenum binaryFormat,
4207 const void *binary,
4208 GLint length)
4209{
4210 Program *programObject = GetValidProgram(context, program);
4211 if (programObject == nullptr)
4212 {
4213 return false;
4214 }
4215
4216 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4217 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4218 programBinaryFormats.end())
4219 {
Jamie Madill437fa652016-05-03 15:13:24 -04004220 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004221 return false;
4222 }
4223
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004224 if (context->hasActiveTransformFeedback(program))
4225 {
4226 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004227 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004228 "Cannot change program binary while program is associated with "
4229 "an active transform feedback object."));
4230 return false;
4231 }
4232
Geoff Langc5629752015-12-07 16:29:04 -05004233 return true;
4234}
4235
4236bool ValidateGetProgramBinaryBase(Context *context,
4237 GLuint program,
4238 GLsizei bufSize,
4239 GLsizei *length,
4240 GLenum *binaryFormat,
4241 void *binary)
4242{
4243 Program *programObject = GetValidProgram(context, program);
4244 if (programObject == nullptr)
4245 {
4246 return false;
4247 }
4248
4249 if (!programObject->isLinked())
4250 {
Jamie Madill437fa652016-05-03 15:13:24 -04004251 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004252 return false;
4253 }
4254
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004255 if (context->getCaps().programBinaryFormats.empty())
4256 {
4257 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4258 return false;
4259 }
4260
Geoff Langc5629752015-12-07 16:29:04 -05004261 return true;
4262}
Jamie Madillc29968b2016-01-20 11:17:23 -05004263
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004264bool ValidateUseProgram(Context *context, GLuint program)
4265{
4266 if (program != 0)
4267 {
4268 Program *programObject = context->getProgram(program);
4269 if (!programObject)
4270 {
4271 // ES 3.1.0 section 7.3 page 72
4272 if (context->getShader(program))
4273 {
Jamie Madill437fa652016-05-03 15:13:24 -04004274 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004275 Error(GL_INVALID_OPERATION,
4276 "Attempted to use a single shader instead of a shader program."));
4277 return false;
4278 }
4279 else
4280 {
Jamie Madill437fa652016-05-03 15:13:24 -04004281 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004282 return false;
4283 }
4284 }
4285 if (!programObject->isLinked())
4286 {
Jamie Madill437fa652016-05-03 15:13:24 -04004287 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004288 return false;
4289 }
4290 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004291 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004292 {
4293 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004294 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004295 Error(GL_INVALID_OPERATION,
4296 "Cannot change active program while transform feedback is unpaused."));
4297 return false;
4298 }
4299
4300 return true;
4301}
4302
Jamie Madillc29968b2016-01-20 11:17:23 -05004303bool ValidateCopyTexImage2D(ValidationContext *context,
4304 GLenum target,
4305 GLint level,
4306 GLenum internalformat,
4307 GLint x,
4308 GLint y,
4309 GLsizei width,
4310 GLsizei height,
4311 GLint border)
4312{
Martin Radev1be913c2016-07-11 17:59:16 +03004313 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004314 {
4315 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4316 0, x, y, width, height, border);
4317 }
4318
Martin Radev1be913c2016-07-11 17:59:16 +03004319 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004320 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4321 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004322}
Jamie Madillc29968b2016-01-20 11:17:23 -05004323
4324bool ValidateFramebufferRenderbuffer(Context *context,
4325 GLenum target,
4326 GLenum attachment,
4327 GLenum renderbuffertarget,
4328 GLuint renderbuffer)
4329{
4330 if (!ValidFramebufferTarget(target) ||
4331 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4332 {
Jamie Madill437fa652016-05-03 15:13:24 -04004333 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004334 return false;
4335 }
4336
4337 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4338 renderbuffertarget, renderbuffer);
4339}
4340
4341bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4342{
4343 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4344 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4345 {
Jamie Madill437fa652016-05-03 15:13:24 -04004346 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004347 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4348 return false;
4349 }
4350
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004351 ASSERT(context->getGLState().getDrawFramebuffer());
4352 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004353 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4354
4355 // This should come first before the check for the default frame buffer
4356 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4357 // rather than INVALID_OPERATION
4358 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4359 {
4360 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4361
4362 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004363 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4364 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004365 {
4366 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004367 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4368 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4369 // 3.1 is still a bit ambiguous about the error, but future specs are
4370 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004371 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004372 return false;
4373 }
4374 else if (bufs[colorAttachment] >= maxColorAttachment)
4375 {
Jamie Madill437fa652016-05-03 15:13:24 -04004376 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004377 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004378 return false;
4379 }
4380 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4381 frameBufferId != 0)
4382 {
4383 // INVALID_OPERATION-GL is bound to buffer and ith argument
4384 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004385 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004386 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4387 return false;
4388 }
4389 }
4390
4391 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4392 // and n is not 1 or bufs is bound to value other than BACK and NONE
4393 if (frameBufferId == 0)
4394 {
4395 if (n != 1)
4396 {
Jamie Madill437fa652016-05-03 15:13:24 -04004397 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004398 "n must be 1 when GL is bound to the default framebuffer"));
4399 return false;
4400 }
4401
4402 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4403 {
Jamie Madill437fa652016-05-03 15:13:24 -04004404 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004405 GL_INVALID_OPERATION,
4406 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4407 return false;
4408 }
4409 }
4410
4411 return true;
4412}
4413
4414bool ValidateCopyTexSubImage2D(Context *context,
4415 GLenum target,
4416 GLint level,
4417 GLint xoffset,
4418 GLint yoffset,
4419 GLint x,
4420 GLint y,
4421 GLsizei width,
4422 GLsizei height)
4423{
Martin Radev1be913c2016-07-11 17:59:16 +03004424 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004425 {
4426 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4427 yoffset, x, y, width, height, 0);
4428 }
4429
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004430 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4431 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004432}
4433
Geoff Lang496c02d2016-10-20 11:38:11 -07004434bool ValidateGetBufferPointervBase(Context *context,
4435 GLenum target,
4436 GLenum pname,
4437 GLsizei *length,
4438 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004439{
Geoff Lang496c02d2016-10-20 11:38:11 -07004440 if (length)
4441 {
4442 *length = 0;
4443 }
4444
4445 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4446 {
4447 context->handleError(
4448 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004449 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004450 return false;
4451 }
4452
Olli Etuaho4f667482016-03-30 15:56:35 +03004453 if (!ValidBufferTarget(context, target))
4454 {
Jamie Madill437fa652016-05-03 15:13:24 -04004455 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004456 return false;
4457 }
4458
Geoff Lang496c02d2016-10-20 11:38:11 -07004459 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004460 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004461 case GL_BUFFER_MAP_POINTER:
4462 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004463
Geoff Lang496c02d2016-10-20 11:38:11 -07004464 default:
4465 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4466 return false;
4467 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004468
4469 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4470 // target bound to zero generate an INVALID_OPERATION error."
4471 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004472 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004473 {
Jamie Madill437fa652016-05-03 15:13:24 -04004474 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004475 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4476 return false;
4477 }
4478
Geoff Lang496c02d2016-10-20 11:38:11 -07004479 if (length)
4480 {
4481 *length = 1;
4482 }
4483
Olli Etuaho4f667482016-03-30 15:56:35 +03004484 return true;
4485}
4486
4487bool ValidateUnmapBufferBase(Context *context, GLenum target)
4488{
4489 if (!ValidBufferTarget(context, target))
4490 {
Jamie Madill437fa652016-05-03 15:13:24 -04004491 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004492 return false;
4493 }
4494
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004495 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004496
4497 if (buffer == nullptr || !buffer->isMapped())
4498 {
Jamie Madill437fa652016-05-03 15:13:24 -04004499 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004500 return false;
4501 }
4502
4503 return true;
4504}
4505
4506bool ValidateMapBufferRangeBase(Context *context,
4507 GLenum target,
4508 GLintptr offset,
4509 GLsizeiptr length,
4510 GLbitfield access)
4511{
4512 if (!ValidBufferTarget(context, target))
4513 {
Jamie Madill437fa652016-05-03 15:13:24 -04004514 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004515 return false;
4516 }
4517
4518 if (offset < 0 || length < 0)
4519 {
Jamie Madill437fa652016-05-03 15:13:24 -04004520 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004521 return false;
4522 }
4523
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004524 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004525
4526 if (!buffer)
4527 {
Jamie Madill437fa652016-05-03 15:13:24 -04004528 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004529 return false;
4530 }
4531
4532 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004533 CheckedNumeric<size_t> checkedOffset(offset);
4534 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004535
Jamie Madille2e406c2016-06-02 13:04:10 -04004536 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004537 {
Jamie Madill437fa652016-05-03 15:13:24 -04004538 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004539 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4540 return false;
4541 }
4542
4543 // Check for invalid bits in the mask
4544 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4545 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4546 GL_MAP_UNSYNCHRONIZED_BIT;
4547
4548 if (access & ~(allAccessBits))
4549 {
Jamie Madill437fa652016-05-03 15:13:24 -04004550 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004551 return false;
4552 }
4553
4554 if (length == 0)
4555 {
Jamie Madill437fa652016-05-03 15:13:24 -04004556 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004557 return false;
4558 }
4559
4560 if (buffer->isMapped())
4561 {
Jamie Madill437fa652016-05-03 15:13:24 -04004562 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004563 return false;
4564 }
4565
4566 // Check for invalid bit combinations
4567 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4568 {
Jamie Madill437fa652016-05-03 15:13:24 -04004569 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004570 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4571 return false;
4572 }
4573
4574 GLbitfield writeOnlyBits =
4575 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4576
4577 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4578 {
Jamie Madill437fa652016-05-03 15:13:24 -04004579 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004580 "Invalid access bits when mapping buffer for reading: 0x%X.",
4581 access));
4582 return false;
4583 }
4584
4585 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4586 {
Jamie Madill437fa652016-05-03 15:13:24 -04004587 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004588 GL_INVALID_OPERATION,
4589 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4590 return false;
4591 }
4592 return true;
4593}
4594
4595bool ValidateFlushMappedBufferRangeBase(Context *context,
4596 GLenum target,
4597 GLintptr offset,
4598 GLsizeiptr length)
4599{
4600 if (offset < 0 || length < 0)
4601 {
Jamie Madill437fa652016-05-03 15:13:24 -04004602 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004603 return false;
4604 }
4605
4606 if (!ValidBufferTarget(context, target))
4607 {
Jamie Madill437fa652016-05-03 15:13:24 -04004608 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004609 return false;
4610 }
4611
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004612 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004613
4614 if (buffer == nullptr)
4615 {
Jamie Madill437fa652016-05-03 15:13:24 -04004616 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004617 return false;
4618 }
4619
4620 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4621 {
Jamie Madill437fa652016-05-03 15:13:24 -04004622 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004623 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4624 return false;
4625 }
4626
4627 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004628 CheckedNumeric<size_t> checkedOffset(offset);
4629 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004630
Jamie Madille2e406c2016-06-02 13:04:10 -04004631 if (!checkedSize.IsValid() ||
4632 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004633 {
Jamie Madill437fa652016-05-03 15:13:24 -04004634 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004635 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4636 return false;
4637 }
4638
4639 return true;
4640}
4641
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004642bool ValidateGenerateMipmap(Context *context, GLenum target)
4643{
4644 if (!ValidTextureTarget(context, target))
4645 {
4646 context->handleError(Error(GL_INVALID_ENUM));
4647 return false;
4648 }
4649
4650 Texture *texture = context->getTargetTexture(target);
4651
4652 if (texture == nullptr)
4653 {
4654 context->handleError(Error(GL_INVALID_OPERATION));
4655 return false;
4656 }
4657
4658 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4659
4660 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4661 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4662 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4663 {
4664 context->handleError(Error(GL_INVALID_OPERATION));
4665 return false;
4666 }
4667
Jamie Madilla3944d42016-07-22 22:13:26 -04004668 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4669 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4670 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004671
4672 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4673 // unsized formats or that are color renderable and filterable. Since we do not track if
4674 // the texture was created with sized or unsized format (only sized formats are stored),
4675 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4676 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4677 // textures since they're the only texture format that can be created with unsized formats
4678 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4679 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004680 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4681 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004682 {
4683 context->handleError(Error(GL_INVALID_OPERATION));
4684 return false;
4685 }
4686
4687 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004688 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004689 {
4690 context->handleError(Error(GL_INVALID_OPERATION));
4691 return false;
4692 }
4693
4694 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004695 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004696 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4697 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4698 {
Geoff Lang55482a12016-11-21 16:54:01 -05004699 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004700 context->handleError(Error(GL_INVALID_OPERATION));
4701 return false;
4702 }
4703
4704 // Cube completeness check
4705 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4706 {
4707 context->handleError(Error(GL_INVALID_OPERATION));
4708 return false;
4709 }
4710
4711 return true;
4712}
4713
Olli Etuaho41997e72016-03-10 13:38:39 +02004714bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4715{
4716 return ValidateGenOrDelete(context, n);
4717}
4718
4719bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4720{
4721 return ValidateGenOrDelete(context, n);
4722}
4723
4724bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4725{
4726 return ValidateGenOrDelete(context, n);
4727}
4728
4729bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4730{
4731 return ValidateGenOrDelete(context, n);
4732}
4733
4734bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4735{
4736 return ValidateGenOrDelete(context, n);
4737}
4738
4739bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4740{
4741 return ValidateGenOrDelete(context, n);
4742}
4743
4744bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4745{
4746 return ValidateGenOrDelete(context, n);
4747}
4748
4749bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4750{
4751 return ValidateGenOrDelete(context, n);
4752}
4753
4754bool ValidateGenOrDelete(Context *context, GLint n)
4755{
4756 if (n < 0)
4757 {
Jamie Madill437fa652016-05-03 15:13:24 -04004758 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004759 return false;
4760 }
4761 return true;
4762}
4763
Geoff Langf41a7152016-09-19 15:11:17 -04004764bool ValidateEnable(Context *context, GLenum cap)
4765{
4766 if (!ValidCap(context, cap, false))
4767 {
4768 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4769 return false;
4770 }
4771
4772 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4773 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4774 {
4775 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4776 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4777
4778 // We also output an error message to the debugger window if tracing is active, so that
4779 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05004780 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04004781 return false;
4782 }
4783
4784 return true;
4785}
4786
4787bool ValidateDisable(Context *context, GLenum cap)
4788{
4789 if (!ValidCap(context, cap, false))
4790 {
4791 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4792 return false;
4793 }
4794
4795 return true;
4796}
4797
4798bool ValidateIsEnabled(Context *context, GLenum cap)
4799{
4800 if (!ValidCap(context, cap, true))
4801 {
4802 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4803 return false;
4804 }
4805
4806 return true;
4807}
4808
Geoff Langff5b2d52016-09-07 11:32:23 -04004809bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4810{
4811 if (!context->getExtensions().robustClientMemory)
4812 {
4813 context->handleError(
4814 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4815 return false;
4816 }
4817
4818 if (bufSize < 0)
4819 {
4820 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4821 return false;
4822 }
4823
4824 return true;
4825}
4826
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004827bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4828{
4829 if (bufSize < numParams)
4830 {
4831 context->handleError(Error(GL_INVALID_OPERATION,
4832 "%u parameters are required but %i were provided.", numParams,
4833 bufSize));
4834 return false;
4835 }
4836
4837 return true;
4838}
4839
Geoff Langff5b2d52016-09-07 11:32:23 -04004840bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4841 GLenum target,
4842 GLenum attachment,
4843 GLenum pname,
4844 GLsizei *numParams)
4845{
4846 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4847 *numParams = 1;
4848
4849 if (!ValidFramebufferTarget(target))
4850 {
4851 context->handleError(Error(GL_INVALID_ENUM));
4852 return false;
4853 }
4854
4855 int clientVersion = context->getClientMajorVersion();
4856
4857 switch (pname)
4858 {
4859 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4860 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4861 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4862 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4863 break;
4864
4865 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4866 if (clientVersion < 3 && !context->getExtensions().sRGB)
4867 {
4868 context->handleError(Error(GL_INVALID_ENUM));
4869 return false;
4870 }
4871 break;
4872
4873 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4874 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4875 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4876 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4877 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4878 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4879 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4880 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4881 if (clientVersion < 3)
4882 {
4883 context->handleError(Error(GL_INVALID_ENUM));
4884 return false;
4885 }
4886 break;
4887
4888 default:
4889 context->handleError(Error(GL_INVALID_ENUM));
4890 return false;
4891 }
4892
4893 // Determine if the attachment is a valid enum
4894 switch (attachment)
4895 {
4896 case GL_BACK:
4897 case GL_FRONT:
4898 case GL_DEPTH:
4899 case GL_STENCIL:
4900 case GL_DEPTH_STENCIL_ATTACHMENT:
4901 if (clientVersion < 3)
4902 {
4903 context->handleError(Error(GL_INVALID_ENUM));
4904 return false;
4905 }
4906 break;
4907
4908 case GL_DEPTH_ATTACHMENT:
4909 case GL_STENCIL_ATTACHMENT:
4910 break;
4911
4912 default:
4913 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4914 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4915 {
4916 context->handleError(Error(GL_INVALID_ENUM));
4917 return false;
4918 }
4919 break;
4920 }
4921
4922 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4923 ASSERT(framebuffer);
4924
4925 if (framebuffer->id() == 0)
4926 {
4927 if (clientVersion < 3)
4928 {
4929 context->handleError(Error(GL_INVALID_OPERATION));
4930 return false;
4931 }
4932
4933 switch (attachment)
4934 {
4935 case GL_BACK:
4936 case GL_DEPTH:
4937 case GL_STENCIL:
4938 break;
4939
4940 default:
4941 context->handleError(Error(GL_INVALID_OPERATION));
4942 return false;
4943 }
4944 }
4945 else
4946 {
4947 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4948 {
4949 // Valid attachment query
4950 }
4951 else
4952 {
4953 switch (attachment)
4954 {
4955 case GL_DEPTH_ATTACHMENT:
4956 case GL_STENCIL_ATTACHMENT:
4957 break;
4958
4959 case GL_DEPTH_STENCIL_ATTACHMENT:
4960 if (!framebuffer->hasValidDepthStencil())
4961 {
4962 context->handleError(Error(GL_INVALID_OPERATION));
4963 return false;
4964 }
4965 break;
4966
4967 default:
4968 context->handleError(Error(GL_INVALID_OPERATION));
4969 return false;
4970 }
4971 }
4972 }
4973
4974 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4975 if (attachmentObject)
4976 {
4977 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4978 attachmentObject->type() == GL_TEXTURE ||
4979 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4980
4981 switch (pname)
4982 {
4983 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4984 if (attachmentObject->type() != GL_RENDERBUFFER &&
4985 attachmentObject->type() != GL_TEXTURE)
4986 {
4987 context->handleError(Error(GL_INVALID_ENUM));
4988 return false;
4989 }
4990 break;
4991
4992 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4993 if (attachmentObject->type() != GL_TEXTURE)
4994 {
4995 context->handleError(Error(GL_INVALID_ENUM));
4996 return false;
4997 }
4998 break;
4999
5000 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
5001 if (attachmentObject->type() != GL_TEXTURE)
5002 {
5003 context->handleError(Error(GL_INVALID_ENUM));
5004 return false;
5005 }
5006 break;
5007
5008 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
5009 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
5010 {
5011 context->handleError(Error(GL_INVALID_OPERATION));
5012 return false;
5013 }
5014 break;
5015
5016 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
5017 if (attachmentObject->type() != GL_TEXTURE)
5018 {
5019 context->handleError(Error(GL_INVALID_ENUM));
5020 return false;
5021 }
5022 break;
5023
5024 default:
5025 break;
5026 }
5027 }
5028 else
5029 {
5030 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
5031 // is NONE, then querying any other pname will generate INVALID_ENUM.
5032
5033 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
5034 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
5035 // INVALID_OPERATION for all other pnames
5036
5037 switch (pname)
5038 {
5039 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5040 break;
5041
5042 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5043 if (clientVersion < 3)
5044 {
5045 context->handleError(Error(GL_INVALID_ENUM));
5046 return false;
5047 }
5048 break;
5049
5050 default:
5051 if (clientVersion < 3)
5052 {
5053 context->handleError(Error(GL_INVALID_ENUM));
5054 return false;
5055 }
5056 else
5057 {
5058 context->handleError(Error(GL_INVALID_OPERATION));
5059 return false;
5060 }
5061 }
5062 }
5063
5064 return true;
5065}
5066
5067bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5068 GLenum target,
5069 GLenum attachment,
5070 GLenum pname,
5071 GLsizei bufSize,
5072 GLsizei *numParams)
5073{
5074 if (!ValidateRobustEntryPoint(context, bufSize))
5075 {
5076 return false;
5077 }
5078
5079 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5080 {
5081 return false;
5082 }
5083
5084 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5085 {
5086 return false;
5087 }
5088
5089 return true;
5090}
5091
5092bool ValidateGetBufferParameteriv(ValidationContext *context,
5093 GLenum target,
5094 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005095 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005096{
Geoff Langebebe1c2016-10-14 12:01:31 -04005097 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005098}
5099
5100bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5101 GLenum target,
5102 GLenum pname,
5103 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005104 GLsizei *length,
5105 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005106{
5107 if (!ValidateRobustEntryPoint(context, bufSize))
5108 {
5109 return false;
5110 }
5111
Geoff Langebebe1c2016-10-14 12:01:31 -04005112 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005113 {
5114 return false;
5115 }
5116
Geoff Langebebe1c2016-10-14 12:01:31 -04005117 if (!ValidateRobustBufferSize(context, bufSize, *length))
5118 {
5119 return false;
5120 }
5121
5122 return true;
5123}
5124
5125bool ValidateGetBufferParameteri64v(ValidationContext *context,
5126 GLenum target,
5127 GLenum pname,
5128 GLint64 *params)
5129{
5130 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5131}
5132
5133bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5134 GLenum target,
5135 GLenum pname,
5136 GLsizei bufSize,
5137 GLsizei *length,
5138 GLint64 *params)
5139{
5140 if (!ValidateRobustEntryPoint(context, bufSize))
5141 {
5142 return false;
5143 }
5144
5145 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5146 {
5147 return false;
5148 }
5149
5150 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005151 {
5152 return false;
5153 }
5154
5155 return true;
5156}
5157
5158bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5159{
5160 // Currently, all GetProgramiv queries return 1 parameter
5161 *numParams = 1;
5162
5163 Program *programObject = GetValidProgram(context, program);
5164 if (!programObject)
5165 {
5166 return false;
5167 }
5168
5169 switch (pname)
5170 {
5171 case GL_DELETE_STATUS:
5172 case GL_LINK_STATUS:
5173 case GL_VALIDATE_STATUS:
5174 case GL_INFO_LOG_LENGTH:
5175 case GL_ATTACHED_SHADERS:
5176 case GL_ACTIVE_ATTRIBUTES:
5177 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5178 case GL_ACTIVE_UNIFORMS:
5179 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5180 break;
5181
5182 case GL_PROGRAM_BINARY_LENGTH:
5183 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5184 {
5185 context->handleError(Error(GL_INVALID_ENUM,
5186 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5187 "GL_OES_get_program_binary or ES 3.0."));
5188 return false;
5189 }
5190 break;
5191
5192 case GL_ACTIVE_UNIFORM_BLOCKS:
5193 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5194 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5195 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5196 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5197 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5198 if (context->getClientMajorVersion() < 3)
5199 {
5200 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5201 return false;
5202 }
5203 break;
5204
Yunchao He61afff12017-03-14 15:34:03 +08005205 case GL_PROGRAM_SEPARABLE:
5206 if (context->getClientVersion() < Version(3, 1))
5207 {
5208 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.1."));
5209 return false;
5210 }
5211 break;
5212
Geoff Langff5b2d52016-09-07 11:32:23 -04005213 default:
5214 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5215 return false;
5216 }
5217
5218 return true;
5219}
5220
5221bool ValidateGetProgramivRobustANGLE(Context *context,
5222 GLuint program,
5223 GLenum pname,
5224 GLsizei bufSize,
5225 GLsizei *numParams)
5226{
5227 if (!ValidateRobustEntryPoint(context, bufSize))
5228 {
5229 return false;
5230 }
5231
5232 if (!ValidateGetProgramiv(context, program, pname, numParams))
5233 {
5234 return false;
5235 }
5236
5237 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5238 {
5239 return false;
5240 }
5241
5242 return true;
5243}
5244
Geoff Lang740d9022016-10-07 11:20:52 -04005245bool ValidateGetRenderbufferParameteriv(Context *context,
5246 GLenum target,
5247 GLenum pname,
5248 GLint *params)
5249{
5250 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5251}
5252
5253bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5254 GLenum target,
5255 GLenum pname,
5256 GLsizei bufSize,
5257 GLsizei *length,
5258 GLint *params)
5259{
5260 if (!ValidateRobustEntryPoint(context, bufSize))
5261 {
5262 return false;
5263 }
5264
5265 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5266 {
5267 return false;
5268 }
5269
5270 if (!ValidateRobustBufferSize(context, bufSize, *length))
5271 {
5272 return false;
5273 }
5274
5275 return true;
5276}
5277
Geoff Langd7d0ed32016-10-07 11:33:51 -04005278bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5279{
5280 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5281}
5282
5283bool ValidateGetShaderivRobustANGLE(Context *context,
5284 GLuint shader,
5285 GLenum pname,
5286 GLsizei bufSize,
5287 GLsizei *length,
5288 GLint *params)
5289{
5290 if (!ValidateRobustEntryPoint(context, bufSize))
5291 {
5292 return false;
5293 }
5294
5295 if (!ValidateGetShaderivBase(context, shader, pname, length))
5296 {
5297 return false;
5298 }
5299
5300 if (!ValidateRobustBufferSize(context, bufSize, *length))
5301 {
5302 return false;
5303 }
5304
5305 return true;
5306}
5307
Geoff Langc1984ed2016-10-07 12:41:00 -04005308bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5309{
5310 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5311}
5312
5313bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5314 GLenum target,
5315 GLenum pname,
5316 GLsizei bufSize,
5317 GLsizei *length,
5318 GLfloat *params)
5319{
5320 if (!ValidateRobustEntryPoint(context, bufSize))
5321 {
5322 return false;
5323 }
5324
5325 if (!ValidateGetTexParameterBase(context, target, pname, length))
5326 {
5327 return false;
5328 }
5329
5330 if (!ValidateRobustBufferSize(context, bufSize, *length))
5331 {
5332 return false;
5333 }
5334
5335 return true;
5336}
5337
5338bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5339{
5340 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5341}
5342
5343bool ValidateGetTexParameterivRobustANGLE(Context *context,
5344 GLenum target,
5345 GLenum pname,
5346 GLsizei bufSize,
5347 GLsizei *length,
5348 GLint *params)
5349{
5350 if (!ValidateRobustEntryPoint(context, bufSize))
5351 {
5352 return false;
5353 }
5354
5355 if (!ValidateGetTexParameterBase(context, target, pname, length))
5356 {
5357 return false;
5358 }
5359
5360 if (!ValidateRobustBufferSize(context, bufSize, *length))
5361 {
5362 return false;
5363 }
5364
5365 return true;
5366}
5367
5368bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5369{
5370 return ValidateTexParameterBase(context, target, pname, -1, &param);
5371}
5372
5373bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5374{
5375 return ValidateTexParameterBase(context, target, pname, -1, params);
5376}
5377
5378bool ValidateTexParameterfvRobustANGLE(Context *context,
5379 GLenum target,
5380 GLenum pname,
5381 GLsizei bufSize,
5382 const GLfloat *params)
5383{
5384 if (!ValidateRobustEntryPoint(context, bufSize))
5385 {
5386 return false;
5387 }
5388
5389 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5390}
5391
5392bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5393{
5394 return ValidateTexParameterBase(context, target, pname, -1, &param);
5395}
5396
5397bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5398{
5399 return ValidateTexParameterBase(context, target, pname, -1, params);
5400}
5401
5402bool ValidateTexParameterivRobustANGLE(Context *context,
5403 GLenum target,
5404 GLenum pname,
5405 GLsizei bufSize,
5406 const GLint *params)
5407{
5408 if (!ValidateRobustEntryPoint(context, bufSize))
5409 {
5410 return false;
5411 }
5412
5413 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5414}
5415
5416bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5417{
5418 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5419}
5420
5421bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5422 GLuint sampler,
5423 GLenum pname,
5424 GLuint bufSize,
5425 GLsizei *length,
5426 GLfloat *params)
5427{
5428 if (!ValidateRobustEntryPoint(context, bufSize))
5429 {
5430 return false;
5431 }
5432
5433 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5434 {
5435 return false;
5436 }
5437
5438 if (!ValidateRobustBufferSize(context, bufSize, *length))
5439 {
5440 return false;
5441 }
5442
5443 return true;
5444}
5445
5446bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5447{
5448 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5449}
5450
5451bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5452 GLuint sampler,
5453 GLenum pname,
5454 GLuint bufSize,
5455 GLsizei *length,
5456 GLint *params)
5457{
5458 if (!ValidateRobustEntryPoint(context, bufSize))
5459 {
5460 return false;
5461 }
5462
5463 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5464 {
5465 return false;
5466 }
5467
5468 if (!ValidateRobustBufferSize(context, bufSize, *length))
5469 {
5470 return false;
5471 }
5472
5473 return true;
5474}
5475
5476bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5477{
5478 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5479}
5480
5481bool ValidateSamplerParameterfv(Context *context,
5482 GLuint sampler,
5483 GLenum pname,
5484 const GLfloat *params)
5485{
5486 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5487}
5488
5489bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5490 GLuint sampler,
5491 GLenum pname,
5492 GLsizei bufSize,
5493 const GLfloat *params)
5494{
5495 if (!ValidateRobustEntryPoint(context, bufSize))
5496 {
5497 return false;
5498 }
5499
5500 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5501}
5502
5503bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5504{
5505 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5506}
5507
5508bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5509{
5510 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5511}
5512
5513bool ValidateSamplerParameterivRobustANGLE(Context *context,
5514 GLuint sampler,
5515 GLenum pname,
5516 GLsizei bufSize,
5517 const GLint *params)
5518{
5519 if (!ValidateRobustEntryPoint(context, bufSize))
5520 {
5521 return false;
5522 }
5523
5524 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5525}
5526
Geoff Lang0b031062016-10-13 14:30:04 -04005527bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5528{
5529 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5530}
5531
5532bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5533 GLuint index,
5534 GLenum pname,
5535 GLsizei bufSize,
5536 GLsizei *length,
5537 GLfloat *params)
5538{
5539 if (!ValidateRobustEntryPoint(context, bufSize))
5540 {
5541 return false;
5542 }
5543
5544 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5545 {
5546 return false;
5547 }
5548
5549 if (!ValidateRobustBufferSize(context, bufSize, *length))
5550 {
5551 return false;
5552 }
5553
5554 return true;
5555}
5556
5557bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5558{
5559 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5560}
5561
5562bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5563 GLuint index,
5564 GLenum pname,
5565 GLsizei bufSize,
5566 GLsizei *length,
5567 GLint *params)
5568{
5569 if (!ValidateRobustEntryPoint(context, bufSize))
5570 {
5571 return false;
5572 }
5573
5574 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5575 {
5576 return false;
5577 }
5578
5579 if (!ValidateRobustBufferSize(context, bufSize, *length))
5580 {
5581 return false;
5582 }
5583
5584 return true;
5585}
5586
5587bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5588{
5589 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5590}
5591
5592bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5593 GLuint index,
5594 GLenum pname,
5595 GLsizei bufSize,
5596 GLsizei *length,
5597 void **pointer)
5598{
5599 if (!ValidateRobustEntryPoint(context, bufSize))
5600 {
5601 return false;
5602 }
5603
5604 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5605 {
5606 return false;
5607 }
5608
5609 if (!ValidateRobustBufferSize(context, bufSize, *length))
5610 {
5611 return false;
5612 }
5613
5614 return true;
5615}
5616
5617bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5618{
5619 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5620}
5621
5622bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5623 GLuint index,
5624 GLenum pname,
5625 GLsizei bufSize,
5626 GLsizei *length,
5627 GLint *params)
5628{
5629 if (!ValidateRobustEntryPoint(context, bufSize))
5630 {
5631 return false;
5632 }
5633
5634 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5635 {
5636 return false;
5637 }
5638
5639 if (!ValidateRobustBufferSize(context, bufSize, *length))
5640 {
5641 return false;
5642 }
5643
5644 return true;
5645}
5646
5647bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5648{
5649 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5650}
5651
5652bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5653 GLuint index,
5654 GLenum pname,
5655 GLsizei bufSize,
5656 GLsizei *length,
5657 GLuint *params)
5658{
5659 if (!ValidateRobustEntryPoint(context, bufSize))
5660 {
5661 return false;
5662 }
5663
5664 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5665 {
5666 return false;
5667 }
5668
5669 if (!ValidateRobustBufferSize(context, bufSize, *length))
5670 {
5671 return false;
5672 }
5673
5674 return true;
5675}
5676
Geoff Lang6899b872016-10-14 11:30:13 -04005677bool ValidateGetActiveUniformBlockiv(Context *context,
5678 GLuint program,
5679 GLuint uniformBlockIndex,
5680 GLenum pname,
5681 GLint *params)
5682{
5683 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5684}
5685
5686bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5687 GLuint program,
5688 GLuint uniformBlockIndex,
5689 GLenum pname,
5690 GLsizei bufSize,
5691 GLsizei *length,
5692 GLint *params)
5693{
5694 if (!ValidateRobustEntryPoint(context, bufSize))
5695 {
5696 return false;
5697 }
5698
5699 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5700 {
5701 return false;
5702 }
5703
5704 if (!ValidateRobustBufferSize(context, bufSize, *length))
5705 {
5706 return false;
5707 }
5708
5709 return true;
5710}
5711
Geoff Lang0a9661f2016-10-20 10:59:20 -07005712bool ValidateGetInternalFormativ(Context *context,
5713 GLenum target,
5714 GLenum internalformat,
5715 GLenum pname,
5716 GLsizei bufSize,
5717 GLint *params)
5718{
5719 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5720 nullptr);
5721}
5722
5723bool ValidateGetInternalFormativRobustANGLE(Context *context,
5724 GLenum target,
5725 GLenum internalformat,
5726 GLenum pname,
5727 GLsizei bufSize,
5728 GLsizei *length,
5729 GLint *params)
5730{
5731 if (!ValidateRobustEntryPoint(context, bufSize))
5732 {
5733 return false;
5734 }
5735
5736 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5737 {
5738 return false;
5739 }
5740
5741 if (!ValidateRobustBufferSize(context, bufSize, *length))
5742 {
5743 return false;
5744 }
5745
5746 return true;
5747}
5748
Shao80957d92017-02-20 21:25:59 +08005749bool ValidateVertexFormatBase(ValidationContext *context,
5750 GLuint attribIndex,
5751 GLint size,
5752 GLenum type,
5753 GLboolean pureInteger)
5754{
5755 const Caps &caps = context->getCaps();
5756 if (attribIndex >= caps.maxVertexAttributes)
5757 {
5758 context->handleError(
5759 Error(GL_INVALID_VALUE, "attribindex must be smaller than MAX_VERTEX_ATTRIBS."));
5760 return false;
5761 }
5762
5763 if (size < 1 || size > 4)
5764 {
5765 context->handleError(Error(GL_INVALID_VALUE, "size must be between one and four."));
5766 }
5767
5768 switch (type)
5769 {
5770 case GL_BYTE:
5771 case GL_UNSIGNED_BYTE:
5772 case GL_SHORT:
5773 case GL_UNSIGNED_SHORT:
5774 break;
5775
5776 case GL_INT:
5777 case GL_UNSIGNED_INT:
5778 if (context->getClientMajorVersion() < 3)
5779 {
5780 context->handleError(
5781 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
5782 return false;
5783 }
5784 break;
5785
5786 case GL_FIXED:
5787 case GL_FLOAT:
5788 if (pureInteger)
5789 {
5790 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
5791 return false;
5792 }
5793 break;
5794
5795 case GL_HALF_FLOAT:
5796 if (context->getClientMajorVersion() < 3)
5797 {
5798 context->handleError(
5799 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
5800 return false;
5801 }
5802 if (pureInteger)
5803 {
5804 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
5805 return false;
5806 }
5807 break;
5808
5809 case GL_INT_2_10_10_10_REV:
5810 case GL_UNSIGNED_INT_2_10_10_10_REV:
5811 if (context->getClientMajorVersion() < 3)
5812 {
5813 context->handleError(
5814 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
5815 return false;
5816 }
5817 if (pureInteger)
5818 {
5819 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
5820 return false;
5821 }
5822 if (size != 4)
5823 {
5824 context->handleError(Error(GL_INVALID_OPERATION,
5825 "Type is INT_2_10_10_10_REV or "
5826 "UNSIGNED_INT_2_10_10_10_REV and size is not 4."));
5827 return false;
5828 }
5829 break;
5830
5831 default:
5832 context->handleError(Error(GL_INVALID_ENUM, "Invalid vertex type."));
5833 return false;
5834 }
5835
5836 return true;
5837}
5838
Jamie Madillc29968b2016-01-20 11:17:23 -05005839} // namespace gl