blob: 8f93a052b13c1efb54292cdb4f07421af656b80f [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
Geoff Lang2d62ab72017-03-23 16:54:40 -04001870bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1871 GLenum type,
1872 GLboolean normalized,
1873 GLsizei stride,
1874 const GLvoid *ptr,
1875 bool pureInteger)
1876{
1877 ASSERT(context->getExtensions().webglCompatibility);
1878
1879 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1880 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1881 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1882 // parameter exceeds 255.
1883 constexpr GLsizei kMaxWebGLStride = 255;
1884 if (stride > kMaxWebGLStride)
1885 {
1886 context->handleError(
1887 Error(GL_INVALID_VALUE, "Stride is over the maximum stride allowed by WebGL."));
1888 return false;
1889 }
1890
1891 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1892 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1893 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1894 // or an INVALID_OPERATION error is generated.
1895 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1896 size_t typeSize = GetVertexFormatTypeSize(internalType);
1897
1898 ASSERT(isPow2(typeSize) && typeSize > 0);
1899 size_t sizeMask = (typeSize - 1);
1900 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1901 {
1902 context->handleError(
1903 Error(GL_INVALID_OPERATION, "Offset is not a multiple of the type size."));
1904 return false;
1905 }
1906
1907 if ((stride & sizeMask) != 0)
1908 {
1909 context->handleError(
1910 Error(GL_INVALID_OPERATION, "Stride is not a multiple of the type size."));
1911 return false;
1912 }
1913
1914 return true;
1915}
1916
Jamie Madillef300b12016-10-07 15:12:09 -04001917Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001918{
He Yunchaoced53ae2016-11-29 15:00:51 +08001919 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1920 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1921 // or program object and INVALID_OPERATION if the provided name identifies an object
1922 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001923
Dian Xiang769769a2015-09-09 15:20:08 -07001924 Program *validProgram = context->getProgram(id);
1925
1926 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001927 {
Dian Xiang769769a2015-09-09 15:20:08 -07001928 if (context->getShader(id))
1929 {
Jamie Madill437fa652016-05-03 15:13:24 -04001930 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001931 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1932 }
1933 else
1934 {
Jamie Madill437fa652016-05-03 15:13:24 -04001935 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001936 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001937 }
Dian Xiang769769a2015-09-09 15:20:08 -07001938
1939 return validProgram;
1940}
1941
Jamie Madillef300b12016-10-07 15:12:09 -04001942Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001943{
1944 // See ValidProgram for spec details.
1945
1946 Shader *validShader = context->getShader(id);
1947
1948 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001949 {
Dian Xiang769769a2015-09-09 15:20:08 -07001950 if (context->getProgram(id))
1951 {
Jamie Madill437fa652016-05-03 15:13:24 -04001952 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001953 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1954 }
1955 else
1956 {
Jamie Madill437fa652016-05-03 15:13:24 -04001957 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001958 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001959 }
Dian Xiang769769a2015-09-09 15:20:08 -07001960
1961 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001962}
1963
Geoff Langb1196682014-07-23 13:47:29 -04001964bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001965{
1966 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1967 {
1968 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1969
Geoff Langaae65a42014-05-26 12:43:44 -04001970 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001971 {
Jamie Madill437fa652016-05-03 15:13:24 -04001972 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001973 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001974 }
1975 }
1976 else
1977 {
1978 switch (attachment)
1979 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001980 case GL_DEPTH_ATTACHMENT:
1981 case GL_STENCIL_ATTACHMENT:
1982 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001983
He Yunchaoced53ae2016-11-29 15:00:51 +08001984 case GL_DEPTH_STENCIL_ATTACHMENT:
1985 if (!context->getExtensions().webglCompatibility &&
1986 context->getClientMajorVersion() < 3)
1987 {
1988 context->handleError(Error(GL_INVALID_ENUM));
1989 return false;
1990 }
1991 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001992
He Yunchaoced53ae2016-11-29 15:00:51 +08001993 default:
1994 context->handleError(Error(GL_INVALID_ENUM));
1995 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001996 }
1997 }
1998
1999 return true;
2000}
2001
Jamie Madille8fb6402017-02-14 17:56:40 -05002002bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08002003 GLenum target,
2004 GLsizei samples,
2005 GLenum internalformat,
2006 GLsizei width,
2007 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002008{
2009 switch (target)
2010 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002011 case GL_RENDERBUFFER:
2012 break;
2013 default:
2014 context->handleError(Error(GL_INVALID_ENUM));
2015 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002016 }
2017
2018 if (width < 0 || height < 0 || samples < 0)
2019 {
Jamie Madill437fa652016-05-03 15:13:24 -04002020 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002021 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002022 }
2023
Jamie Madill4e0e6f82017-02-17 11:06:03 -05002024 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
2025 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
2026
2027 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04002028 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002029 {
Jamie Madill437fa652016-05-03 15:13:24 -04002030 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002031 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002032 }
2033
2034 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
2035 // 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 -08002036 // only sized internal formats.
Jamie Madill4e0e6f82017-02-17 11:06:03 -05002037 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(convertedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04002038 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002039 {
Jamie Madill437fa652016-05-03 15:13:24 -04002040 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002041 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002042 }
2043
Geoff Langaae65a42014-05-26 12:43:44 -04002044 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002045 {
Jamie Madill437fa652016-05-03 15:13:24 -04002046 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002047 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002048 }
2049
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002050 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002051 if (handle == 0)
2052 {
Jamie Madill437fa652016-05-03 15:13:24 -04002053 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002054 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002055 }
2056
2057 return true;
2058}
2059
He Yunchaoced53ae2016-11-29 15:00:51 +08002060bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
2061 GLenum target,
2062 GLenum attachment,
2063 GLenum renderbuffertarget,
2064 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002065{
Shannon Woods1da3cf62014-06-27 15:32:23 -04002066 if (!ValidFramebufferTarget(target))
2067 {
Jamie Madill437fa652016-05-03 15:13:24 -04002068 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002069 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04002070 }
2071
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002072 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002073
Jamie Madill84115c92015-04-23 15:00:07 -04002074 ASSERT(framebuffer);
2075 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002076 {
Jamie Madill437fa652016-05-03 15:13:24 -04002077 context->handleError(
2078 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002079 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002080 }
2081
Jamie Madillb4472272014-07-03 10:38:55 -04002082 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002083 {
Jamie Madillb4472272014-07-03 10:38:55 -04002084 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002085 }
2086
Jamie Madillab9d82c2014-01-21 16:38:14 -05002087 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2088 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2089 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2090 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2091 if (renderbuffer != 0)
2092 {
2093 if (!context->getRenderbuffer(renderbuffer))
2094 {
Jamie Madill437fa652016-05-03 15:13:24 -04002095 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002096 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05002097 }
2098 }
2099
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002100 return true;
2101}
2102
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002103bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002104 GLint srcX0,
2105 GLint srcY0,
2106 GLint srcX1,
2107 GLint srcY1,
2108 GLint dstX0,
2109 GLint dstY0,
2110 GLint dstX1,
2111 GLint dstY1,
2112 GLbitfield mask,
2113 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002114{
2115 switch (filter)
2116 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002117 case GL_NEAREST:
2118 break;
2119 case GL_LINEAR:
2120 break;
2121 default:
2122 context->handleError(Error(GL_INVALID_ENUM));
2123 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002124 }
2125
2126 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
2127 {
Jamie Madill437fa652016-05-03 15:13:24 -04002128 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002129 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002130 }
2131
2132 if (mask == 0)
2133 {
2134 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
2135 // buffers are copied.
2136 return false;
2137 }
2138
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002139 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
2140 // color buffer, leaving only nearest being unfiltered from above
2141 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
2142 {
Jamie Madill437fa652016-05-03 15:13:24 -04002143 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002144 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002145 }
2146
Jamie Madill51f40ec2016-06-15 14:06:00 -04002147 const auto &glState = context->getGLState();
2148 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2149 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05002150
2151 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002152 {
Jamie Madill437fa652016-05-03 15:13:24 -04002153 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002154 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002155 }
2156
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002157 if (readFramebuffer->id() == drawFramebuffer->id())
2158 {
2159 context->handleError(Error(GL_INVALID_OPERATION));
2160 return false;
2161 }
2162
Jamie Madill51f40ec2016-06-15 14:06:00 -04002163 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002164 {
Jamie Madill437fa652016-05-03 15:13:24 -04002165 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002166 return false;
2167 }
2168
Jamie Madill51f40ec2016-06-15 14:06:00 -04002169 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002170 {
Jamie Madill437fa652016-05-03 15:13:24 -04002171 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002172 return false;
2173 }
2174
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002175 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002176 {
Jamie Madill437fa652016-05-03 15:13:24 -04002177 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002178 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002179 }
2180
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002181 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2182
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002183 if (mask & GL_COLOR_BUFFER_BIT)
2184 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002185 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002186 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002187
He Yunchao66a41a22016-12-15 16:45:05 +08002188 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002189 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002190 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002191
Geoff Langa15472a2015-08-11 11:48:03 -04002192 for (size_t drawbufferIdx = 0;
2193 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002194 {
Geoff Langa15472a2015-08-11 11:48:03 -04002195 const FramebufferAttachment *attachment =
2196 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2197 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002198 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002199 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002200
Geoff Langb2f3d052013-08-13 12:49:27 -04002201 // The GL ES 3.0.2 spec (pg 193) states that:
2202 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002203 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2204 // as well
2205 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2206 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002207 // Changes with EXT_color_buffer_float:
2208 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002209 GLenum readComponentType = readFormat.info->componentType;
2210 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002211 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002212 readComponentType == GL_SIGNED_NORMALIZED);
2213 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2214 drawComponentType == GL_SIGNED_NORMALIZED);
2215
2216 if (extensions.colorBufferFloat)
2217 {
2218 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2219 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2220
2221 if (readFixedOrFloat != drawFixedOrFloat)
2222 {
Jamie Madill437fa652016-05-03 15:13:24 -04002223 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002224 "If the read buffer contains fixed-point or "
2225 "floating-point values, the draw buffer "
2226 "must as well."));
2227 return false;
2228 }
2229 }
2230 else if (readFixedPoint != drawFixedPoint)
2231 {
Jamie Madill437fa652016-05-03 15:13:24 -04002232 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002233 "If the read buffer contains fixed-point "
2234 "values, the draw buffer must as well."));
2235 return false;
2236 }
2237
2238 if (readComponentType == GL_UNSIGNED_INT &&
2239 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002240 {
Jamie Madill437fa652016-05-03 15:13:24 -04002241 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002242 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002243 }
2244
Jamie Madill6163c752015-12-07 16:32:59 -05002245 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002246 {
Jamie Madill437fa652016-05-03 15:13:24 -04002247 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002248 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002249 }
2250
Jamie Madilla3944d42016-07-22 22:13:26 -04002251 if (readColorBuffer->getSamples() > 0 &&
2252 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002253 {
Jamie Madill437fa652016-05-03 15:13:24 -04002254 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002255 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002256 }
2257 }
2258 }
2259
Jamie Madilla3944d42016-07-22 22:13:26 -04002260 if ((readFormat.info->componentType == GL_INT ||
2261 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2262 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002263 {
Jamie Madill437fa652016-05-03 15:13:24 -04002264 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002265 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002266 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002267 }
He Yunchao66a41a22016-12-15 16:45:05 +08002268 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2269 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2270 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2271 // situation is an application error that would lead to a crash in ANGLE.
2272 else if (drawFramebuffer->hasEnabledDrawBuffer())
2273 {
2274 context->handleError(Error(
2275 GL_INVALID_OPERATION,
2276 "Attempt to read from a missing color attachment of a complete framebuffer."));
2277 return false;
2278 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002279 }
2280
He Yunchaoced53ae2016-11-29 15:00:51 +08002281 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002282 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2283 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002284 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002285 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002286 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002287 const gl::FramebufferAttachment *readBuffer =
2288 readFramebuffer->getAttachment(attachments[i]);
2289 const gl::FramebufferAttachment *drawBuffer =
2290 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002291
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002292 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002293 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002294 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002295 {
Jamie Madill437fa652016-05-03 15:13:24 -04002296 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002297 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002298 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002299
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002300 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002301 {
Jamie Madill437fa652016-05-03 15:13:24 -04002302 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002303 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002304 }
2305 }
He Yunchao66a41a22016-12-15 16:45:05 +08002306 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2307 else if (drawBuffer)
2308 {
2309 context->handleError(Error(GL_INVALID_OPERATION,
2310 "Attempt to read from a missing depth/stencil "
2311 "attachment of a complete framebuffer."));
2312 return false;
2313 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002314 }
2315 }
2316
2317 return true;
2318}
2319
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002320bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002321 GLint x,
2322 GLint y,
2323 GLsizei width,
2324 GLsizei height,
2325 GLenum format,
2326 GLenum type,
2327 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002328{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002329 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2330}
2331
2332bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2333 GLint x,
2334 GLint y,
2335 GLsizei width,
2336 GLsizei height,
2337 GLenum format,
2338 GLenum type,
2339 GLsizei bufSize,
2340 GLsizei *length,
2341 GLvoid *pixels)
2342{
2343 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002344 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002345 return false;
2346 }
2347
Geoff Lang62fce5b2016-09-30 10:46:35 -04002348 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2349 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002350 {
Geoff Langb1196682014-07-23 13:47:29 -04002351 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002352 }
2353
Geoff Lang62fce5b2016-09-30 10:46:35 -04002354 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002355 {
Geoff Langb1196682014-07-23 13:47:29 -04002356 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002357 }
2358
Jamie Madillc29968b2016-01-20 11:17:23 -05002359 return true;
2360}
2361
2362bool ValidateReadnPixelsEXT(Context *context,
2363 GLint x,
2364 GLint y,
2365 GLsizei width,
2366 GLsizei height,
2367 GLenum format,
2368 GLenum type,
2369 GLsizei bufSize,
2370 GLvoid *pixels)
2371{
2372 if (bufSize < 0)
2373 {
Jamie Madill437fa652016-05-03 15:13:24 -04002374 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002375 return false;
2376 }
2377
Geoff Lang62fce5b2016-09-30 10:46:35 -04002378 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2379 pixels);
2380}
Jamie Madill26e91952014-03-05 15:01:27 -05002381
Geoff Lang62fce5b2016-09-30 10:46:35 -04002382bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2383 GLint x,
2384 GLint y,
2385 GLsizei width,
2386 GLsizei height,
2387 GLenum format,
2388 GLenum type,
2389 GLsizei bufSize,
2390 GLsizei *length,
2391 GLvoid *data)
2392{
2393 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002394 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002395 return false;
2396 }
2397
Geoff Lang62fce5b2016-09-30 10:46:35 -04002398 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002399 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002400 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002401 }
2402
Geoff Lang62fce5b2016-09-30 10:46:35 -04002403 if (!ValidateRobustBufferSize(context, bufSize, *length))
2404 {
2405 return false;
2406 }
2407
2408 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002409}
2410
Olli Etuaho41997e72016-03-10 13:38:39 +02002411bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002412{
2413 if (!context->getExtensions().occlusionQueryBoolean &&
2414 !context->getExtensions().disjointTimerQuery)
2415 {
Jamie Madill437fa652016-05-03 15:13:24 -04002416 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002417 return false;
2418 }
2419
Olli Etuaho41997e72016-03-10 13:38:39 +02002420 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002421}
2422
Olli Etuaho41997e72016-03-10 13:38:39 +02002423bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002424{
2425 if (!context->getExtensions().occlusionQueryBoolean &&
2426 !context->getExtensions().disjointTimerQuery)
2427 {
Jamie Madill437fa652016-05-03 15:13:24 -04002428 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002429 return false;
2430 }
2431
Olli Etuaho41997e72016-03-10 13:38:39 +02002432 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002433}
2434
2435bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002436{
2437 if (!ValidQueryType(context, target))
2438 {
Jamie Madill437fa652016-05-03 15:13:24 -04002439 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002440 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002441 }
2442
2443 if (id == 0)
2444 {
Jamie Madill437fa652016-05-03 15:13:24 -04002445 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002446 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002447 }
2448
2449 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2450 // of zero, if the active query object name for <target> is non-zero (for the
2451 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2452 // the active query for either target is non-zero), if <id> is the name of an
2453 // existing query object whose type does not match <target>, or if <id> is the
2454 // active query object name for any query type, the error INVALID_OPERATION is
2455 // generated.
2456
2457 // Ensure no other queries are active
2458 // NOTE: If other queries than occlusion are supported, we will need to check
2459 // separately that:
2460 // a) The query ID passed is not the current active query for any target/type
2461 // b) There are no active queries for the requested target (and in the case
2462 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2463 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002464
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002465 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002466 {
Jamie Madill437fa652016-05-03 15:13:24 -04002467 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002468 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002469 }
2470
2471 Query *queryObject = context->getQuery(id, true, target);
2472
2473 // check that name was obtained with glGenQueries
2474 if (!queryObject)
2475 {
Jamie Madill437fa652016-05-03 15:13:24 -04002476 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002477 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002478 }
2479
2480 // check for type mismatch
2481 if (queryObject->getType() != target)
2482 {
Jamie Madill437fa652016-05-03 15:13:24 -04002483 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002484 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002485 }
2486
2487 return true;
2488}
2489
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002490bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2491{
2492 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002493 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002494 {
Jamie Madill437fa652016-05-03 15:13:24 -04002495 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002496 return false;
2497 }
2498
2499 return ValidateBeginQueryBase(context, target, id);
2500}
2501
2502bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002503{
2504 if (!ValidQueryType(context, target))
2505 {
Jamie Madill437fa652016-05-03 15:13:24 -04002506 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002507 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002508 }
2509
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002510 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002511
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002512 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002513 {
Jamie Madill437fa652016-05-03 15:13:24 -04002514 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002515 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002516 }
2517
Jamie Madill45c785d2014-05-13 14:09:34 -04002518 return true;
2519}
2520
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002521bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2522{
2523 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002524 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002525 {
Jamie Madill437fa652016-05-03 15:13:24 -04002526 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002527 return false;
2528 }
2529
2530 return ValidateEndQueryBase(context, target);
2531}
2532
2533bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2534{
2535 if (!context->getExtensions().disjointTimerQuery)
2536 {
Jamie Madill437fa652016-05-03 15:13:24 -04002537 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002538 return false;
2539 }
2540
2541 if (target != GL_TIMESTAMP_EXT)
2542 {
Jamie Madill437fa652016-05-03 15:13:24 -04002543 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002544 return false;
2545 }
2546
2547 Query *queryObject = context->getQuery(id, true, target);
2548 if (queryObject == nullptr)
2549 {
Jamie Madill437fa652016-05-03 15:13:24 -04002550 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002551 return false;
2552 }
2553
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002554 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002555 {
Jamie Madill437fa652016-05-03 15:13:24 -04002556 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002557 return false;
2558 }
2559
2560 return true;
2561}
2562
Geoff Lang2186c382016-10-14 10:54:54 -04002563bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002564{
Geoff Lang2186c382016-10-14 10:54:54 -04002565 if (numParams)
2566 {
2567 *numParams = 0;
2568 }
2569
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002570 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2571 {
Jamie Madill437fa652016-05-03 15:13:24 -04002572 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002573 return false;
2574 }
2575
2576 switch (pname)
2577 {
2578 case GL_CURRENT_QUERY_EXT:
2579 if (target == GL_TIMESTAMP_EXT)
2580 {
Jamie Madill437fa652016-05-03 15:13:24 -04002581 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002582 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2583 return false;
2584 }
2585 break;
2586 case GL_QUERY_COUNTER_BITS_EXT:
2587 if (!context->getExtensions().disjointTimerQuery ||
2588 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2589 {
Jamie Madill437fa652016-05-03 15:13:24 -04002590 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002591 return false;
2592 }
2593 break;
2594 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002595 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002596 return false;
2597 }
2598
Geoff Lang2186c382016-10-14 10:54:54 -04002599 if (numParams)
2600 {
2601 // All queries return only one value
2602 *numParams = 1;
2603 }
2604
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002605 return true;
2606}
2607
2608bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2609{
2610 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002611 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002612 {
Jamie Madill437fa652016-05-03 15:13:24 -04002613 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002614 return false;
2615 }
2616
Geoff Lang2186c382016-10-14 10:54:54 -04002617 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002618}
2619
Geoff Lang2186c382016-10-14 10:54:54 -04002620bool ValidateGetQueryivRobustANGLE(Context *context,
2621 GLenum target,
2622 GLenum pname,
2623 GLsizei bufSize,
2624 GLsizei *length,
2625 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002626{
Geoff Lang2186c382016-10-14 10:54:54 -04002627 if (!ValidateRobustEntryPoint(context, bufSize))
2628 {
2629 return false;
2630 }
2631
2632 if (!ValidateGetQueryivBase(context, target, pname, length))
2633 {
2634 return false;
2635 }
2636
2637 if (!ValidateRobustBufferSize(context, bufSize, *length))
2638 {
2639 return false;
2640 }
2641
2642 return true;
2643}
2644
2645bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2646{
2647 if (numParams)
2648 {
2649 *numParams = 0;
2650 }
2651
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002652 Query *queryObject = context->getQuery(id, false, GL_NONE);
2653
2654 if (!queryObject)
2655 {
Jamie Madill437fa652016-05-03 15:13:24 -04002656 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002657 return false;
2658 }
2659
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002660 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002661 {
Jamie Madill437fa652016-05-03 15:13:24 -04002662 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002663 return false;
2664 }
2665
2666 switch (pname)
2667 {
2668 case GL_QUERY_RESULT_EXT:
2669 case GL_QUERY_RESULT_AVAILABLE_EXT:
2670 break;
2671
2672 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002673 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002674 return false;
2675 }
2676
Geoff Lang2186c382016-10-14 10:54:54 -04002677 if (numParams)
2678 {
2679 *numParams = 1;
2680 }
2681
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002682 return true;
2683}
2684
2685bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2686{
2687 if (!context->getExtensions().disjointTimerQuery)
2688 {
Jamie Madill437fa652016-05-03 15:13:24 -04002689 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002690 return false;
2691 }
Geoff Lang2186c382016-10-14 10:54:54 -04002692 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2693}
2694
2695bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2696 GLuint id,
2697 GLenum pname,
2698 GLsizei bufSize,
2699 GLsizei *length,
2700 GLint *params)
2701{
2702 if (!context->getExtensions().disjointTimerQuery)
2703 {
2704 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2705 return false;
2706 }
2707
2708 if (!ValidateRobustEntryPoint(context, bufSize))
2709 {
2710 return false;
2711 }
2712
2713 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2714 {
2715 return false;
2716 }
2717
2718 if (!ValidateRobustBufferSize(context, bufSize, *length))
2719 {
2720 return false;
2721 }
2722
2723 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002724}
2725
2726bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2727{
2728 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002729 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002730 {
Jamie Madill437fa652016-05-03 15:13:24 -04002731 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002732 return false;
2733 }
Geoff Lang2186c382016-10-14 10:54:54 -04002734 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2735}
2736
2737bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2738 GLuint id,
2739 GLenum pname,
2740 GLsizei bufSize,
2741 GLsizei *length,
2742 GLuint *params)
2743{
2744 if (!context->getExtensions().disjointTimerQuery &&
2745 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2746 {
2747 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2748 return false;
2749 }
2750
2751 if (!ValidateRobustEntryPoint(context, bufSize))
2752 {
2753 return false;
2754 }
2755
2756 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2757 {
2758 return false;
2759 }
2760
2761 if (!ValidateRobustBufferSize(context, bufSize, *length))
2762 {
2763 return false;
2764 }
2765
2766 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002767}
2768
2769bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2770{
2771 if (!context->getExtensions().disjointTimerQuery)
2772 {
Jamie Madill437fa652016-05-03 15:13:24 -04002773 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002774 return false;
2775 }
Geoff Lang2186c382016-10-14 10:54:54 -04002776 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2777}
2778
2779bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2780 GLuint id,
2781 GLenum pname,
2782 GLsizei bufSize,
2783 GLsizei *length,
2784 GLint64 *params)
2785{
2786 if (!context->getExtensions().disjointTimerQuery)
2787 {
2788 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2789 return false;
2790 }
2791
2792 if (!ValidateRobustEntryPoint(context, bufSize))
2793 {
2794 return false;
2795 }
2796
2797 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2798 {
2799 return false;
2800 }
2801
2802 if (!ValidateRobustBufferSize(context, bufSize, *length))
2803 {
2804 return false;
2805 }
2806
2807 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002808}
2809
2810bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2811{
2812 if (!context->getExtensions().disjointTimerQuery)
2813 {
Jamie Madill437fa652016-05-03 15:13:24 -04002814 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002815 return false;
2816 }
Geoff Lang2186c382016-10-14 10:54:54 -04002817 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2818}
2819
2820bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2821 GLuint id,
2822 GLenum pname,
2823 GLsizei bufSize,
2824 GLsizei *length,
2825 GLuint64 *params)
2826{
2827 if (!context->getExtensions().disjointTimerQuery)
2828 {
2829 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2830 return false;
2831 }
2832
2833 if (!ValidateRobustEntryPoint(context, bufSize))
2834 {
2835 return false;
2836 }
2837
2838 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2839 {
2840 return false;
2841 }
2842
2843 if (!ValidateRobustBufferSize(context, bufSize, *length))
2844 {
2845 return false;
2846 }
2847
2848 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002849}
2850
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002851bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002852 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002853 GLuint program,
2854 GLint location,
2855 GLsizei count)
2856{
2857 // Check for ES31 program uniform entry points
2858 if (context->getClientVersion() < Version(3, 1))
2859 {
2860 context->handleError(Error(GL_INVALID_OPERATION));
2861 return false;
2862 }
2863
2864 const LinkedUniform *uniform = nullptr;
2865 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002866 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2867 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002868}
2869
Frank Henigmana98a6472017-02-02 21:38:32 -05002870bool ValidateProgramUniform1iv(gl::Context *context,
2871 GLuint program,
2872 GLint location,
2873 GLsizei count,
2874 const GLint *value)
2875{
2876 // Check for ES31 program uniform entry points
2877 if (context->getClientVersion() < Version(3, 1))
2878 {
2879 context->handleError(Error(GL_INVALID_OPERATION));
2880 return false;
2881 }
2882
2883 const LinkedUniform *uniform = nullptr;
2884 gl::Program *programObject = GetValidProgram(context, program);
2885 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2886 ValidateUniform1ivValue(context, uniform->type, count, value);
2887}
2888
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002889bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002890 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002891 GLuint program,
2892 GLint location,
2893 GLsizei count,
2894 GLboolean transpose)
2895{
2896 // Check for ES31 program uniform entry points
2897 if (context->getClientVersion() < Version(3, 1))
2898 {
2899 context->handleError(Error(GL_INVALID_OPERATION));
2900 return false;
2901 }
2902
2903 const LinkedUniform *uniform = nullptr;
2904 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002905 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2906 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002907}
2908
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002909bool ValidateUniform(gl::Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002910{
2911 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002912 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002913 {
Jamie Madill437fa652016-05-03 15:13:24 -04002914 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002915 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002916 }
2917
Jamie Madill62d31cb2015-09-11 13:25:51 -04002918 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002919 gl::Program *programObject = context->getGLState().getProgram();
2920 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2921 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002922}
2923
Frank Henigmana98a6472017-02-02 21:38:32 -05002924bool ValidateUniform1iv(gl::Context *context, GLint location, GLsizei count, const GLint *value)
2925{
2926 const LinkedUniform *uniform = nullptr;
2927 gl::Program *programObject = context->getGLState().getProgram();
2928 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2929 ValidateUniform1ivValue(context, uniform->type, count, value);
2930}
2931
He Yunchaoced53ae2016-11-29 15:00:51 +08002932bool ValidateUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002933 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002934 GLint location,
2935 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002936 GLboolean transpose)
2937{
2938 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002939 int rows = VariableRowCount(valueType);
2940 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002941 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002942 {
Jamie Madill437fa652016-05-03 15:13:24 -04002943 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002944 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002945 }
2946
Martin Radev1be913c2016-07-11 17:59:16 +03002947 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002948 {
Jamie Madill437fa652016-05-03 15:13:24 -04002949 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002950 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002951 }
2952
Jamie Madill62d31cb2015-09-11 13:25:51 -04002953 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002954 gl::Program *programObject = context->getGLState().getProgram();
2955 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2956 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002957}
2958
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002959bool ValidateStateQuery(ValidationContext *context,
2960 GLenum pname,
2961 GLenum *nativeType,
2962 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002963{
2964 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2965 {
Jamie Madill437fa652016-05-03 15:13:24 -04002966 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002967 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002968 }
2969
Jamie Madill0af26e12015-03-05 19:54:33 -05002970 const Caps &caps = context->getCaps();
2971
Jamie Madill893ab082014-05-16 16:56:10 -04002972 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2973 {
2974 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2975
Jamie Madill0af26e12015-03-05 19:54:33 -05002976 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002977 {
Jamie Madill437fa652016-05-03 15:13:24 -04002978 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002979 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002980 }
2981 }
2982
2983 switch (pname)
2984 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002985 case GL_TEXTURE_BINDING_2D:
2986 case GL_TEXTURE_BINDING_CUBE_MAP:
2987 case GL_TEXTURE_BINDING_3D:
2988 case GL_TEXTURE_BINDING_2D_ARRAY:
2989 break;
2990 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2991 if (!context->getExtensions().eglStreamConsumerExternal &&
2992 !context->getExtensions().eglImageExternal)
2993 {
2994 context->handleError(Error(GL_INVALID_ENUM,
2995 "Neither NV_EGL_stream_consumer_external nor "
2996 "GL_OES_EGL_image_external extensions enabled"));
2997 return false;
2998 }
2999 break;
Jamie Madill893ab082014-05-16 16:56:10 -04003000
He Yunchaoced53ae2016-11-29 15:00:51 +08003001 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3002 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04003003 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04003004 if (context->getGLState().getReadFramebuffer()->checkStatus(
3005 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04003006 {
Jamie Madill437fa652016-05-03 15:13:24 -04003007 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003008 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003009 }
3010
Jamie Madill51f40ec2016-06-15 14:06:00 -04003011 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
3012 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03003013
3014 if (framebuffer->getReadBufferState() == GL_NONE)
3015 {
3016 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3017 return false;
3018 }
3019
Jamie Madillb6bda4a2015-04-20 12:53:26 -04003020 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04003021 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04003022 {
Jamie Madill437fa652016-05-03 15:13:24 -04003023 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003024 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003025 }
3026 }
3027 break;
3028
He Yunchaoced53ae2016-11-29 15:00:51 +08003029 default:
3030 break;
Jamie Madill893ab082014-05-16 16:56:10 -04003031 }
3032
3033 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04003034 if (*numParams == 0)
3035 {
3036 return false;
3037 }
3038
3039 return true;
3040}
3041
3042bool ValidateRobustStateQuery(ValidationContext *context,
3043 GLenum pname,
3044 GLsizei bufSize,
3045 GLenum *nativeType,
3046 unsigned int *numParams)
3047{
3048 if (!ValidateRobustEntryPoint(context, bufSize))
3049 {
3050 return false;
3051 }
3052
3053 if (!ValidateStateQuery(context, pname, nativeType, numParams))
3054 {
3055 return false;
3056 }
3057
3058 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04003059 {
3060 return false;
3061 }
3062
3063 return true;
3064}
3065
Jamie Madillc29968b2016-01-20 11:17:23 -05003066bool ValidateCopyTexImageParametersBase(ValidationContext *context,
3067 GLenum target,
3068 GLint level,
3069 GLenum internalformat,
3070 bool isSubImage,
3071 GLint xoffset,
3072 GLint yoffset,
3073 GLint zoffset,
3074 GLint x,
3075 GLint y,
3076 GLsizei width,
3077 GLsizei height,
3078 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04003079 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04003080{
Jamie Madill560a8d82014-05-21 13:06:20 -04003081 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
3082 {
Jamie Madill437fa652016-05-03 15:13:24 -04003083 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003084 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003085 }
3086
He Yunchaoced53ae2016-11-29 15:00:51 +08003087 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3088 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04003089 {
Jamie Madill437fa652016-05-03 15:13:24 -04003090 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003091 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003092 }
3093
3094 if (border != 0)
3095 {
Jamie Madill437fa652016-05-03 15:13:24 -04003096 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003097 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003098 }
3099
3100 if (!ValidMipLevel(context, target, level))
3101 {
Jamie Madill437fa652016-05-03 15:13:24 -04003102 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003103 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003104 }
3105
Jamie Madill51f40ec2016-06-15 14:06:00 -04003106 const auto &state = context->getGLState();
3107 auto readFramebuffer = state.getReadFramebuffer();
3108 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003109 {
Jamie Madill437fa652016-05-03 15:13:24 -04003110 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003111 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003112 }
3113
Jamie Madill51f40ec2016-06-15 14:06:00 -04003114 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003115 {
Jamie Madill437fa652016-05-03 15:13:24 -04003116 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003117 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003118 }
3119
Martin Radev138064f2016-07-15 12:03:41 +03003120 if (readFramebuffer->getReadBufferState() == GL_NONE)
3121 {
3122 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3123 return false;
3124 }
3125
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003126 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3127 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003128 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003129 // situation is an application error that would lead to a crash in ANGLE.
3130 if (readFramebuffer->getReadColorbuffer() == nullptr)
3131 {
3132 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3133 return false;
3134 }
3135
Geoff Langaae65a42014-05-26 12:43:44 -04003136 const gl::Caps &caps = context->getCaps();
3137
Geoff Langaae65a42014-05-26 12:43:44 -04003138 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003139 switch (target)
3140 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003141 case GL_TEXTURE_2D:
3142 maxDimension = caps.max2DTextureSize;
3143 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003144
He Yunchaoced53ae2016-11-29 15:00:51 +08003145 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3146 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3147 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3148 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3149 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3150 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3151 maxDimension = caps.maxCubeMapTextureSize;
3152 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003153
He Yunchaoced53ae2016-11-29 15:00:51 +08003154 case GL_TEXTURE_2D_ARRAY:
3155 maxDimension = caps.max2DTextureSize;
3156 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003157
He Yunchaoced53ae2016-11-29 15:00:51 +08003158 case GL_TEXTURE_3D:
3159 maxDimension = caps.max3DTextureSize;
3160 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003161
He Yunchaoced53ae2016-11-29 15:00:51 +08003162 default:
3163 context->handleError(Error(GL_INVALID_ENUM));
3164 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003165 }
3166
Jamie Madillc29968b2016-01-20 11:17:23 -05003167 gl::Texture *texture =
3168 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003169 if (!texture)
3170 {
Jamie Madill437fa652016-05-03 15:13:24 -04003171 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003172 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003173 }
3174
Geoff Lang69cce582015-09-17 13:20:36 -04003175 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003176 {
Jamie Madill437fa652016-05-03 15:13:24 -04003177 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003178 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003179 }
3180
Geoff Lang5d601382014-07-22 15:14:06 -04003181 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3182
3183 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003184 {
Jamie Madill437fa652016-05-03 15:13:24 -04003185 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003186 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003187 }
3188
Geoff Lang44ff5a72017-02-03 15:15:43 -05003189 if (formatInfo.compressed &&
3190 !ValidCompressedImageSize(context, internalformat, xoffset, yoffset, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003191 {
Jamie Madill437fa652016-05-03 15:13:24 -04003192 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003193 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003194 }
3195
3196 if (isSubImage)
3197 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003198 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3199 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3200 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003201 {
Jamie Madill437fa652016-05-03 15:13:24 -04003202 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003203 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003204 }
3205 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003206 else
3207 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003208 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003209 {
Jamie Madill437fa652016-05-03 15:13:24 -04003210 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003211 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003212 }
3213
Geoff Langeb66a6e2016-10-31 13:06:12 -04003214 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003215 {
Jamie Madill437fa652016-05-03 15:13:24 -04003216 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003217 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003218 }
3219
3220 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003221 if (static_cast<int>(width) > maxLevelDimension ||
3222 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003223 {
Jamie Madill437fa652016-05-03 15:13:24 -04003224 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003225 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003226 }
3227 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003228
Jamie Madill0c8abca2016-07-22 20:21:26 -04003229 if (textureFormatOut)
3230 {
3231 *textureFormatOut = texture->getFormat(target, level);
3232 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003233
3234 // Detect texture copying feedback loops for WebGL.
3235 if (context->getExtensions().webglCompatibility)
3236 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05003237 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05003238 {
3239 context->handleError(Error(GL_INVALID_OPERATION,
3240 "Texture copying feedback loop formed between Framebuffer "
3241 "and specified Texture level."));
3242 return false;
3243 }
3244 }
3245
Jamie Madill560a8d82014-05-21 13:06:20 -04003246 return true;
3247}
3248
Jiajia Qind9671222016-11-29 16:30:31 +08003249bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003250{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003251 switch (mode)
3252 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003253 case GL_POINTS:
3254 case GL_LINES:
3255 case GL_LINE_LOOP:
3256 case GL_LINE_STRIP:
3257 case GL_TRIANGLES:
3258 case GL_TRIANGLE_STRIP:
3259 case GL_TRIANGLE_FAN:
3260 break;
3261 default:
3262 context->handleError(Error(GL_INVALID_ENUM));
3263 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003264 }
3265
Jamie Madill250d33f2014-06-06 17:09:03 -04003266 if (count < 0)
3267 {
Jamie Madill437fa652016-05-03 15:13:24 -04003268 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003269 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003270 }
3271
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003272 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003273
Jamie Madill250d33f2014-06-06 17:09:03 -04003274 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003275 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003276 {
Jamie Madill437fa652016-05-03 15:13:24 -04003277 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003278 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003279 }
3280
Jamie Madillcbcde722017-01-06 14:50:00 -05003281 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3282 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003283 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003284 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3285 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003286 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003287 const FramebufferAttachment *dsAttachment =
3288 framebuffer->getStencilOrDepthStencilAttachment();
3289 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003290 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003291 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003292
3293 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3294 bool differentWritemasks =
3295 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3296 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3297 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3298 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3299
3300 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003301 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003302 if (!context->getExtensions().webglCompatibility)
3303 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003304 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3305 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003306 }
Jamie Madill437fa652016-05-03 15:13:24 -04003307 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003308 return false;
3309 }
Jamie Madillac528012014-06-20 13:21:23 -04003310 }
3311
Jamie Madill51f40ec2016-06-15 14:06:00 -04003312 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003313 {
Jamie Madill437fa652016-05-03 15:13:24 -04003314 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003315 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003316 }
3317
Geoff Lang7dd2e102014-11-10 15:19:26 -05003318 gl::Program *program = state.getProgram();
3319 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003320 {
Jamie Madill437fa652016-05-03 15:13:24 -04003321 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003322 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003323 }
3324
Geoff Lang7dd2e102014-11-10 15:19:26 -05003325 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003326 {
Jamie Madill437fa652016-05-03 15:13:24 -04003327 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003328 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003329 }
3330
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003331 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003332 for (unsigned int uniformBlockIndex = 0;
3333 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003334 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003335 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003336 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003337 const OffsetBindingPointer<Buffer> &uniformBuffer =
3338 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003339
Geoff Lang5d124a62015-09-15 13:03:27 -04003340 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003341 {
3342 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003343 context->handleError(
3344 Error(GL_INVALID_OPERATION,
3345 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003346 return false;
3347 }
3348
Geoff Lang5d124a62015-09-15 13:03:27 -04003349 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003350 if (uniformBufferSize == 0)
3351 {
3352 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003353 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003354 }
3355
Jamie Madill62d31cb2015-09-11 13:25:51 -04003356 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003357 {
3358 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003359 context->handleError(
3360 Error(GL_INVALID_OPERATION,
3361 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003362 return false;
3363 }
3364 }
3365
Jamie Madilla4595b82017-01-11 17:36:34 -05003366 // Detect rendering feedback loops for WebGL.
3367 if (context->getExtensions().webglCompatibility)
3368 {
3369 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3370 {
3371 context->handleError(
3372 Error(GL_INVALID_OPERATION,
3373 "Rendering feedback loop formed between Framebuffer and active Texture."));
3374 return false;
3375 }
3376 }
3377
Jamie Madill250d33f2014-06-06 17:09:03 -04003378 // No-op if zero count
3379 return (count > 0);
3380}
3381
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003382bool ValidateDrawArrays(ValidationContext *context,
3383 GLenum mode,
3384 GLint first,
3385 GLsizei count,
3386 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003387{
Jamie Madillfd716582014-06-06 17:09:04 -04003388 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003389 {
Jamie Madill437fa652016-05-03 15:13:24 -04003390 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003391 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003392 }
3393
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003394 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003395 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003396 if (curTransformFeedback && curTransformFeedback->isActive() &&
3397 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003398 {
3399 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003400 // that does not match the current transform feedback object's draw mode (if transform
3401 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003402 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003403 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003404 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003405 }
3406
Jiajia Qind9671222016-11-29 16:30:31 +08003407 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003408 {
3409 return false;
3410 }
3411
Corentin Wallez71168a02016-12-19 15:11:18 -08003412 // Check the computation of maxVertex doesn't overflow.
3413 // - first < 0 or count < 0 have been checked as an error condition
3414 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3415 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3416 ASSERT(count > 0 && first >= 0);
3417 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3418 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003419 {
3420 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3421 return false;
3422 }
3423
Corentin Wallez71168a02016-12-19 15:11:18 -08003424 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003425 {
3426 return false;
3427 }
3428
3429 return true;
3430}
3431
He Yunchaoced53ae2016-11-29 15:00:51 +08003432bool ValidateDrawArraysInstanced(Context *context,
3433 GLenum mode,
3434 GLint first,
3435 GLsizei count,
3436 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003437{
3438 if (primcount < 0)
3439 {
Jamie Madill437fa652016-05-03 15:13:24 -04003440 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003441 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003442 }
3443
Jamie Madill2b976812014-08-25 15:47:49 -04003444 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003445 {
3446 return false;
3447 }
3448
3449 // No-op if zero primitive count
3450 return (primcount > 0);
3451}
3452
Geoff Lang87a93302014-09-16 13:29:43 -04003453static bool ValidateDrawInstancedANGLE(Context *context)
3454{
3455 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003456 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003457
Geoff Lang7dd2e102014-11-10 15:19:26 -05003458 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003459
Jiawei-Shao2597fb62016-12-09 16:38:02 +08003460 const auto &attribs = state.getVertexArray()->getVertexAttributes();
3461 const auto &bindings = state.getVertexArray()->getVertexBindings();
Jamie Madill63805b42015-08-25 13:17:39 -04003462 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003463 {
Jiawei-Shao2597fb62016-12-09 16:38:02 +08003464 const VertexAttribute &attrib = attribs[attributeIndex];
3465 const VertexBinding &binding = bindings[attrib.bindingIndex];
3466 if (program->isAttribLocationActive(attributeIndex) && binding.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003467 {
3468 return true;
3469 }
3470 }
3471
Jamie Madill437fa652016-05-03 15:13:24 -04003472 context->handleError(Error(GL_INVALID_OPERATION,
3473 "ANGLE_instanced_arrays requires that at least one active attribute"
3474 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003475 return false;
3476}
3477
He Yunchaoced53ae2016-11-29 15:00:51 +08003478bool ValidateDrawArraysInstancedANGLE(Context *context,
3479 GLenum mode,
3480 GLint first,
3481 GLsizei count,
3482 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003483{
3484 if (!ValidateDrawInstancedANGLE(context))
3485 {
3486 return false;
3487 }
3488
3489 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3490}
3491
Jiajia Qind9671222016-11-29 16:30:31 +08003492bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003493{
Jamie Madill250d33f2014-06-06 17:09:03 -04003494 switch (type)
3495 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003496 case GL_UNSIGNED_BYTE:
3497 case GL_UNSIGNED_SHORT:
3498 break;
3499 case GL_UNSIGNED_INT:
3500 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3501 {
3502 context->handleError(Error(GL_INVALID_ENUM));
3503 return false;
3504 }
3505 break;
3506 default:
3507 context->handleError(Error(GL_INVALID_ENUM));
3508 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003509 }
3510
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003511 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003512
3513 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003514 if (curTransformFeedback && curTransformFeedback->isActive() &&
3515 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003516 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003517 // It is an invalid operation to call DrawElements, DrawRangeElements or
3518 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003519 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003520 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003521 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003522 }
3523
Jiajia Qind9671222016-11-29 16:30:31 +08003524 return true;
3525}
3526
3527bool ValidateDrawElements(ValidationContext *context,
3528 GLenum mode,
3529 GLsizei count,
3530 GLenum type,
3531 const GLvoid *indices,
3532 GLsizei primcount,
3533 IndexRange *indexRangeOut)
3534{
3535 if (!ValidateDrawElementsBase(context, type))
3536 return false;
3537
3538 const State &state = context->getGLState();
3539
Jamie Madill250d33f2014-06-06 17:09:03 -04003540 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003541 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003542 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003543 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04003544 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003545 }
3546
He Yunchaoced53ae2016-11-29 15:00:51 +08003547 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003548 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003549
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003550 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3551
3552 if (context->getExtensions().webglCompatibility)
3553 {
3554 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3555 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3556 {
3557 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3558 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3559 // data type passed to the call, or an INVALID_OPERATION error is generated.
3560 context->handleError(Error(GL_INVALID_OPERATION,
3561 "indices must be a multiple of the element type size."));
3562 return false;
3563 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003564
3565 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3566 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3567 // error is generated.
3568 if (reinterpret_cast<intptr_t>(indices) < 0)
3569 {
3570 context->handleError(Error(GL_INVALID_VALUE, "Offset < 0."));
3571 return false;
3572 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003573 }
3574
3575 if (context->getExtensions().webglCompatibility ||
3576 !context->getGLState().areClientArraysEnabled())
3577 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003578 if (!elementArrayBuffer && count > 0)
3579 {
3580 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3581 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3582 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3583 context->handleError(Error(GL_INVALID_OPERATION,
3584 "There is no element array buffer bound and count > 0."));
3585 return false;
3586 }
3587 }
3588
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003589 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003590 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003591 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003592 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003593 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3594 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3595 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3596 constexpr uint64_t kMaxTypeSize = 8;
3597 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3598 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3599 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003600
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003601 uint64_t typeSize = typeBytes;
3602 uint64_t elementCount = static_cast<uint64_t>(count);
3603 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3604
3605 // Doing the multiplication here is overflow-safe
3606 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3607
3608 // The offset can be any value, check for overflows
3609 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3610 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003611 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003612 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003613 return false;
3614 }
3615
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003616 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3617 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003618 {
3619 context->handleError(
3620 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
3621 return false;
3622 }
3623 }
3624 else if (!indices)
3625 {
3626 // This is an application error that would normally result in a crash,
3627 // but we catch it and return an error
3628 context->handleError(
3629 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003630 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003631 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003632 }
3633
Jiajia Qind9671222016-11-29 16:30:31 +08003634 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003635 {
3636 return false;
3637 }
3638
Jamie Madill2b976812014-08-25 15:47:49 -04003639 // Use max index to validate if our vertex buffers are large enough for the pull.
3640 // TODO: offer fast path, with disabled index validation.
3641 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3642 if (elementArrayBuffer)
3643 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003644 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003645 Error error =
3646 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3647 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003648 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003649 {
Jamie Madill437fa652016-05-03 15:13:24 -04003650 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003651 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003652 }
3653 }
3654 else
3655 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003656 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003657 }
3658
Jamie Madille79b1e12015-11-04 16:36:37 -05003659 // If we use an index greater than our maximum supported index range, return an error.
3660 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3661 // return an error if possible here.
3662 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3663 {
Jamie Madill437fa652016-05-03 15:13:24 -04003664 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003665 return false;
3666 }
3667
Corentin Wallez92db6942016-12-09 13:10:36 -05003668 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3669 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003670 {
3671 return false;
3672 }
3673
Geoff Lang3edfe032015-09-04 16:38:24 -04003674 // No op if there are no real indices in the index data (all are primitive restart).
3675 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003676}
3677
Geoff Langb1196682014-07-23 13:47:29 -04003678bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003679 GLenum mode,
3680 GLsizei count,
3681 GLenum type,
3682 const GLvoid *indices,
3683 GLsizei primcount,
3684 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003685{
3686 if (primcount < 0)
3687 {
Jamie Madill437fa652016-05-03 15:13:24 -04003688 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003689 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003690 }
3691
Jamie Madill2b976812014-08-25 15:47:49 -04003692 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003693 {
3694 return false;
3695 }
3696
3697 // No-op zero primitive count
3698 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003699}
3700
Geoff Lang3edfe032015-09-04 16:38:24 -04003701bool ValidateDrawElementsInstancedANGLE(Context *context,
3702 GLenum mode,
3703 GLsizei count,
3704 GLenum type,
3705 const GLvoid *indices,
3706 GLsizei primcount,
3707 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003708{
3709 if (!ValidateDrawInstancedANGLE(context))
3710 {
3711 return false;
3712 }
3713
He Yunchaoced53ae2016-11-29 15:00:51 +08003714 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3715 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003716}
3717
He Yunchaoced53ae2016-11-29 15:00:51 +08003718bool ValidateFramebufferTextureBase(Context *context,
3719 GLenum target,
3720 GLenum attachment,
3721 GLuint texture,
3722 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003723{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003724 if (!ValidFramebufferTarget(target))
3725 {
Jamie Madill437fa652016-05-03 15:13:24 -04003726 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003727 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003728 }
3729
3730 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003731 {
3732 return false;
3733 }
3734
Jamie Madill55ec3b12014-07-03 10:38:57 -04003735 if (texture != 0)
3736 {
3737 gl::Texture *tex = context->getTexture(texture);
3738
3739 if (tex == NULL)
3740 {
Jamie Madill437fa652016-05-03 15:13:24 -04003741 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003742 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003743 }
3744
3745 if (level < 0)
3746 {
Jamie Madill437fa652016-05-03 15:13:24 -04003747 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003748 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003749 }
3750 }
3751
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003752 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003753 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003754
Jamie Madill84115c92015-04-23 15:00:07 -04003755 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003756 {
Jamie Madill437fa652016-05-03 15:13:24 -04003757 context->handleError(
3758 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003759 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003760 }
3761
3762 return true;
3763}
3764
He Yunchaoced53ae2016-11-29 15:00:51 +08003765bool ValidateFramebufferTexture2D(Context *context,
3766 GLenum target,
3767 GLenum attachment,
3768 GLenum textarget,
3769 GLuint texture,
3770 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003771{
He Yunchaoced53ae2016-11-29 15:00:51 +08003772 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3773 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003774 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3775 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003776 {
Jamie Madill437fa652016-05-03 15:13:24 -04003777 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003778 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003779 }
3780
3781 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003782 {
3783 return false;
3784 }
3785
Jamie Madill55ec3b12014-07-03 10:38:57 -04003786 if (texture != 0)
3787 {
3788 gl::Texture *tex = context->getTexture(texture);
3789 ASSERT(tex);
3790
Jamie Madill2a6564e2014-07-11 09:53:19 -04003791 const gl::Caps &caps = context->getCaps();
3792
Jamie Madill55ec3b12014-07-03 10:38:57 -04003793 switch (textarget)
3794 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003795 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003796 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003797 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003798 {
Jamie Madill437fa652016-05-03 15:13:24 -04003799 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003800 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003801 }
3802 if (tex->getTarget() != GL_TEXTURE_2D)
3803 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003804 context->handleError(Error(GL_INVALID_OPERATION,
3805 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003806 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003807 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003808 }
3809 break;
3810
He Yunchaoced53ae2016-11-29 15:00:51 +08003811 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3812 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3813 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3814 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3815 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3816 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003817 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003818 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003819 {
Jamie Madill437fa652016-05-03 15:13:24 -04003820 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003821 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003822 }
3823 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3824 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003825 context->handleError(Error(GL_INVALID_OPERATION,
3826 "Textarget must match the texture target type."));
3827 return false;
3828 }
3829 }
3830 break;
3831
3832 case GL_TEXTURE_2D_MULTISAMPLE:
3833 {
3834 if (context->getClientVersion() < ES_3_1)
3835 {
3836 context->handleError(Error(GL_INVALID_OPERATION,
3837 "Texture target requires at least OpenGL ES 3.1."));
3838 return false;
3839 }
3840
3841 if (level != 0)
3842 {
3843 context->handleError(
3844 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
3845 return false;
3846 }
3847 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
3848 {
3849 context->handleError(Error(GL_INVALID_OPERATION,
3850 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003851 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003852 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003853 }
3854 break;
3855
He Yunchaoced53ae2016-11-29 15:00:51 +08003856 default:
3857 context->handleError(Error(GL_INVALID_ENUM));
3858 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003859 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003860
Jamie Madilla3944d42016-07-22 22:13:26 -04003861 const Format &format = tex->getFormat(textarget, level);
3862 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003863 {
Jamie Madill437fa652016-05-03 15:13:24 -04003864 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003865 return false;
3866 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003867 }
3868
Jamie Madill570f7c82014-07-03 10:38:54 -04003869 return true;
3870}
3871
Geoff Langb1196682014-07-23 13:47:29 -04003872bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003873{
3874 if (program == 0)
3875 {
Jamie Madill437fa652016-05-03 15:13:24 -04003876 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003877 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003878 }
3879
Dian Xiang769769a2015-09-09 15:20:08 -07003880 gl::Program *programObject = GetValidProgram(context, program);
3881 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003882 {
3883 return false;
3884 }
3885
Jamie Madill0063c512014-08-25 15:47:53 -04003886 if (!programObject || !programObject->isLinked())
3887 {
Jamie Madill437fa652016-05-03 15:13:24 -04003888 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003889 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003890 }
3891
Geoff Lang7dd2e102014-11-10 15:19:26 -05003892 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003893 {
Jamie Madill437fa652016-05-03 15:13:24 -04003894 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003895 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003896 }
3897
Jamie Madill0063c512014-08-25 15:47:53 -04003898 return true;
3899}
3900
He Yunchaoced53ae2016-11-29 15:00:51 +08003901bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003902{
3903 return ValidateGetUniformBase(context, program, location);
3904}
3905
He Yunchaoced53ae2016-11-29 15:00:51 +08003906bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003907{
Jamie Madill78f41802014-08-25 15:47:55 -04003908 return ValidateGetUniformBase(context, program, location);
3909}
3910
Geoff Langf41d0ee2016-10-07 13:04:23 -04003911static bool ValidateSizedGetUniform(Context *context,
3912 GLuint program,
3913 GLint location,
3914 GLsizei bufSize,
3915 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003916{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003917 if (length)
3918 {
3919 *length = 0;
3920 }
3921
Jamie Madill78f41802014-08-25 15:47:55 -04003922 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003923 {
Jamie Madill78f41802014-08-25 15:47:55 -04003924 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003925 }
3926
Geoff Langf41d0ee2016-10-07 13:04:23 -04003927 if (bufSize < 0)
3928 {
3929 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3930 return false;
3931 }
3932
Jamie Madilla502c742014-08-28 17:19:13 -04003933 gl::Program *programObject = context->getProgram(program);
3934 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003935
Jamie Madill78f41802014-08-25 15:47:55 -04003936 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003937 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003938 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003939 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003940 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003941 context->handleError(
3942 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003943 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003944 }
3945
Geoff Langf41d0ee2016-10-07 13:04:23 -04003946 if (length)
3947 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003948 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003949 }
3950
Jamie Madill0063c512014-08-25 15:47:53 -04003951 return true;
3952}
3953
He Yunchaoced53ae2016-11-29 15:00:51 +08003954bool ValidateGetnUniformfvEXT(Context *context,
3955 GLuint program,
3956 GLint location,
3957 GLsizei bufSize,
3958 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003959{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003960 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003961}
3962
He Yunchaoced53ae2016-11-29 15:00:51 +08003963bool ValidateGetnUniformivEXT(Context *context,
3964 GLuint program,
3965 GLint location,
3966 GLsizei bufSize,
3967 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003968{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003969 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3970}
3971
3972bool ValidateGetUniformfvRobustANGLE(Context *context,
3973 GLuint program,
3974 GLint location,
3975 GLsizei bufSize,
3976 GLsizei *length,
3977 GLfloat *params)
3978{
3979 if (!ValidateRobustEntryPoint(context, bufSize))
3980 {
3981 return false;
3982 }
3983
3984 // bufSize is validated in ValidateSizedGetUniform
3985 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3986}
3987
3988bool ValidateGetUniformivRobustANGLE(Context *context,
3989 GLuint program,
3990 GLint location,
3991 GLsizei bufSize,
3992 GLsizei *length,
3993 GLint *params)
3994{
3995 if (!ValidateRobustEntryPoint(context, bufSize))
3996 {
3997 return false;
3998 }
3999
4000 // bufSize is validated in ValidateSizedGetUniform
4001 return ValidateSizedGetUniform(context, program, location, bufSize, length);
4002}
4003
4004bool ValidateGetUniformuivRobustANGLE(Context *context,
4005 GLuint program,
4006 GLint location,
4007 GLsizei bufSize,
4008 GLsizei *length,
4009 GLuint *params)
4010{
4011 if (!ValidateRobustEntryPoint(context, bufSize))
4012 {
4013 return false;
4014 }
4015
4016 if (context->getClientMajorVersion() < 3)
4017 {
4018 context->handleError(
4019 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
4020 return false;
4021 }
4022
4023 // bufSize is validated in ValidateSizedGetUniform
4024 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04004025}
4026
He Yunchaoced53ae2016-11-29 15:00:51 +08004027bool ValidateDiscardFramebufferBase(Context *context,
4028 GLenum target,
4029 GLsizei numAttachments,
4030 const GLenum *attachments,
4031 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07004032{
4033 if (numAttachments < 0)
4034 {
Jamie Madill437fa652016-05-03 15:13:24 -04004035 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07004036 return false;
4037 }
4038
4039 for (GLsizei i = 0; i < numAttachments; ++i)
4040 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02004041 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07004042 {
4043 if (defaultFramebuffer)
4044 {
Jamie Madill437fa652016-05-03 15:13:24 -04004045 context->handleError(Error(
4046 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07004047 return false;
4048 }
4049
4050 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
4051 {
Jamie Madill437fa652016-05-03 15:13:24 -04004052 context->handleError(Error(GL_INVALID_OPERATION,
4053 "Requested color attachment is greater than the maximum "
4054 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07004055 return false;
4056 }
4057 }
4058 else
4059 {
4060 switch (attachments[i])
4061 {
He Yunchaoced53ae2016-11-29 15:00:51 +08004062 case GL_DEPTH_ATTACHMENT:
4063 case GL_STENCIL_ATTACHMENT:
4064 case GL_DEPTH_STENCIL_ATTACHMENT:
4065 if (defaultFramebuffer)
4066 {
4067 context->handleError(
4068 Error(GL_INVALID_ENUM,
4069 "Invalid attachment when the default framebuffer is bound"));
4070 return false;
4071 }
4072 break;
4073 case GL_COLOR:
4074 case GL_DEPTH:
4075 case GL_STENCIL:
4076 if (!defaultFramebuffer)
4077 {
4078 context->handleError(
4079 Error(GL_INVALID_ENUM,
4080 "Invalid attachment when the default framebuffer is not bound"));
4081 return false;
4082 }
4083 break;
4084 default:
4085 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07004086 return false;
Austin Kinross08332632015-05-05 13:35:47 -07004087 }
4088 }
4089 }
4090
4091 return true;
4092}
4093
Austin Kinross6ee1e782015-05-29 17:05:37 -07004094bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
4095{
4096 // Note that debug marker calls must not set error state
4097
4098 if (length < 0)
4099 {
4100 return false;
4101 }
4102
4103 if (marker == nullptr)
4104 {
4105 return false;
4106 }
4107
4108 return true;
4109}
4110
4111bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
4112{
4113 // Note that debug marker calls must not set error state
4114
4115 if (length < 0)
4116 {
4117 return false;
4118 }
4119
4120 if (length > 0 && marker == nullptr)
4121 {
4122 return false;
4123 }
4124
4125 return true;
4126}
4127
Geoff Langdcab33b2015-07-21 13:03:16 -04004128bool ValidateEGLImageTargetTexture2DOES(Context *context,
4129 egl::Display *display,
4130 GLenum target,
4131 egl::Image *image)
4132{
Geoff Langa8406172015-07-21 16:53:39 -04004133 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4134 {
Jamie Madill437fa652016-05-03 15:13:24 -04004135 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004136 return false;
4137 }
4138
4139 switch (target)
4140 {
4141 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004142 if (!context->getExtensions().eglImage)
4143 {
4144 context->handleError(Error(
4145 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4146 }
4147 break;
4148
4149 case GL_TEXTURE_EXTERNAL_OES:
4150 if (!context->getExtensions().eglImageExternal)
4151 {
4152 context->handleError(Error(
4153 GL_INVALID_ENUM,
4154 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4155 }
Geoff Langa8406172015-07-21 16:53:39 -04004156 break;
4157
4158 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004159 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004160 return false;
4161 }
4162
4163 if (!display->isValidImage(image))
4164 {
Jamie Madill437fa652016-05-03 15:13:24 -04004165 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004166 return false;
4167 }
4168
4169 if (image->getSamples() > 0)
4170 {
Jamie Madill437fa652016-05-03 15:13:24 -04004171 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004172 "cannot create a 2D texture from a multisampled EGL image."));
4173 return false;
4174 }
4175
Jamie Madilla3944d42016-07-22 22:13:26 -04004176 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004177 if (!textureCaps.texturable)
4178 {
Jamie Madill437fa652016-05-03 15:13:24 -04004179 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004180 "EGL image internal format is not supported as a texture."));
4181 return false;
4182 }
4183
Geoff Langdcab33b2015-07-21 13:03:16 -04004184 return true;
4185}
4186
4187bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4188 egl::Display *display,
4189 GLenum target,
4190 egl::Image *image)
4191{
Geoff Langa8406172015-07-21 16:53:39 -04004192 if (!context->getExtensions().eglImage)
4193 {
Jamie Madill437fa652016-05-03 15:13:24 -04004194 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004195 return false;
4196 }
4197
4198 switch (target)
4199 {
4200 case GL_RENDERBUFFER:
4201 break;
4202
4203 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004204 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004205 return false;
4206 }
4207
4208 if (!display->isValidImage(image))
4209 {
Jamie Madill437fa652016-05-03 15:13:24 -04004210 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004211 return false;
4212 }
4213
Jamie Madilla3944d42016-07-22 22:13:26 -04004214 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004215 if (!textureCaps.renderable)
4216 {
Jamie Madill437fa652016-05-03 15:13:24 -04004217 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004218 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4219 return false;
4220 }
4221
Geoff Langdcab33b2015-07-21 13:03:16 -04004222 return true;
4223}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004224
4225bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4226{
Geoff Lang36167ab2015-12-07 10:27:14 -05004227 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004228 {
4229 // The default VAO should always exist
4230 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004231 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004232 return false;
4233 }
4234
4235 return true;
4236}
4237
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004238bool ValidateLinkProgram(Context *context, GLuint program)
4239{
4240 if (context->hasActiveTransformFeedback(program))
4241 {
4242 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004243 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004244 "Cannot link program while program is associated with an active "
4245 "transform feedback object."));
4246 return false;
4247 }
4248 return true;
4249}
4250
Geoff Langc5629752015-12-07 16:29:04 -05004251bool ValidateProgramBinaryBase(Context *context,
4252 GLuint program,
4253 GLenum binaryFormat,
4254 const void *binary,
4255 GLint length)
4256{
4257 Program *programObject = GetValidProgram(context, program);
4258 if (programObject == nullptr)
4259 {
4260 return false;
4261 }
4262
4263 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4264 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4265 programBinaryFormats.end())
4266 {
Jamie Madill437fa652016-05-03 15:13:24 -04004267 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004268 return false;
4269 }
4270
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004271 if (context->hasActiveTransformFeedback(program))
4272 {
4273 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004274 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004275 "Cannot change program binary while program is associated with "
4276 "an active transform feedback object."));
4277 return false;
4278 }
4279
Geoff Langc5629752015-12-07 16:29:04 -05004280 return true;
4281}
4282
4283bool ValidateGetProgramBinaryBase(Context *context,
4284 GLuint program,
4285 GLsizei bufSize,
4286 GLsizei *length,
4287 GLenum *binaryFormat,
4288 void *binary)
4289{
4290 Program *programObject = GetValidProgram(context, program);
4291 if (programObject == nullptr)
4292 {
4293 return false;
4294 }
4295
4296 if (!programObject->isLinked())
4297 {
Jamie Madill437fa652016-05-03 15:13:24 -04004298 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004299 return false;
4300 }
4301
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004302 if (context->getCaps().programBinaryFormats.empty())
4303 {
4304 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4305 return false;
4306 }
4307
Geoff Langc5629752015-12-07 16:29:04 -05004308 return true;
4309}
Jamie Madillc29968b2016-01-20 11:17:23 -05004310
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004311bool ValidateUseProgram(Context *context, GLuint program)
4312{
4313 if (program != 0)
4314 {
4315 Program *programObject = context->getProgram(program);
4316 if (!programObject)
4317 {
4318 // ES 3.1.0 section 7.3 page 72
4319 if (context->getShader(program))
4320 {
Jamie Madill437fa652016-05-03 15:13:24 -04004321 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004322 Error(GL_INVALID_OPERATION,
4323 "Attempted to use a single shader instead of a shader program."));
4324 return false;
4325 }
4326 else
4327 {
Jamie Madill437fa652016-05-03 15:13:24 -04004328 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004329 return false;
4330 }
4331 }
4332 if (!programObject->isLinked())
4333 {
Jamie Madill437fa652016-05-03 15:13:24 -04004334 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004335 return false;
4336 }
4337 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004338 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004339 {
4340 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004341 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004342 Error(GL_INVALID_OPERATION,
4343 "Cannot change active program while transform feedback is unpaused."));
4344 return false;
4345 }
4346
4347 return true;
4348}
4349
Jamie Madillc29968b2016-01-20 11:17:23 -05004350bool ValidateCopyTexImage2D(ValidationContext *context,
4351 GLenum target,
4352 GLint level,
4353 GLenum internalformat,
4354 GLint x,
4355 GLint y,
4356 GLsizei width,
4357 GLsizei height,
4358 GLint border)
4359{
Martin Radev1be913c2016-07-11 17:59:16 +03004360 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004361 {
4362 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4363 0, x, y, width, height, border);
4364 }
4365
Martin Radev1be913c2016-07-11 17:59:16 +03004366 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004367 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4368 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004369}
Jamie Madillc29968b2016-01-20 11:17:23 -05004370
4371bool ValidateFramebufferRenderbuffer(Context *context,
4372 GLenum target,
4373 GLenum attachment,
4374 GLenum renderbuffertarget,
4375 GLuint renderbuffer)
4376{
4377 if (!ValidFramebufferTarget(target) ||
4378 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4379 {
Jamie Madill437fa652016-05-03 15:13:24 -04004380 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004381 return false;
4382 }
4383
4384 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4385 renderbuffertarget, renderbuffer);
4386}
4387
4388bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4389{
4390 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4391 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4392 {
Jamie Madill437fa652016-05-03 15:13:24 -04004393 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004394 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4395 return false;
4396 }
4397
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004398 ASSERT(context->getGLState().getDrawFramebuffer());
4399 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004400 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4401
4402 // This should come first before the check for the default frame buffer
4403 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4404 // rather than INVALID_OPERATION
4405 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4406 {
4407 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4408
4409 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004410 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4411 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004412 {
4413 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004414 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4415 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4416 // 3.1 is still a bit ambiguous about the error, but future specs are
4417 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004418 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004419 return false;
4420 }
4421 else if (bufs[colorAttachment] >= maxColorAttachment)
4422 {
Jamie Madill437fa652016-05-03 15:13:24 -04004423 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004424 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004425 return false;
4426 }
4427 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4428 frameBufferId != 0)
4429 {
4430 // INVALID_OPERATION-GL is bound to buffer and ith argument
4431 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004432 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004433 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4434 return false;
4435 }
4436 }
4437
4438 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4439 // and n is not 1 or bufs is bound to value other than BACK and NONE
4440 if (frameBufferId == 0)
4441 {
4442 if (n != 1)
4443 {
Jamie Madill437fa652016-05-03 15:13:24 -04004444 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004445 "n must be 1 when GL is bound to the default framebuffer"));
4446 return false;
4447 }
4448
4449 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4450 {
Jamie Madill437fa652016-05-03 15:13:24 -04004451 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004452 GL_INVALID_OPERATION,
4453 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4454 return false;
4455 }
4456 }
4457
4458 return true;
4459}
4460
4461bool ValidateCopyTexSubImage2D(Context *context,
4462 GLenum target,
4463 GLint level,
4464 GLint xoffset,
4465 GLint yoffset,
4466 GLint x,
4467 GLint y,
4468 GLsizei width,
4469 GLsizei height)
4470{
Martin Radev1be913c2016-07-11 17:59:16 +03004471 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004472 {
4473 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4474 yoffset, x, y, width, height, 0);
4475 }
4476
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004477 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4478 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004479}
4480
Geoff Lang496c02d2016-10-20 11:38:11 -07004481bool ValidateGetBufferPointervBase(Context *context,
4482 GLenum target,
4483 GLenum pname,
4484 GLsizei *length,
4485 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004486{
Geoff Lang496c02d2016-10-20 11:38:11 -07004487 if (length)
4488 {
4489 *length = 0;
4490 }
4491
4492 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4493 {
4494 context->handleError(
4495 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004496 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004497 return false;
4498 }
4499
Olli Etuaho4f667482016-03-30 15:56:35 +03004500 if (!ValidBufferTarget(context, target))
4501 {
Jamie Madill437fa652016-05-03 15:13:24 -04004502 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004503 return false;
4504 }
4505
Geoff Lang496c02d2016-10-20 11:38:11 -07004506 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004507 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004508 case GL_BUFFER_MAP_POINTER:
4509 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004510
Geoff Lang496c02d2016-10-20 11:38:11 -07004511 default:
4512 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4513 return false;
4514 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004515
4516 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4517 // target bound to zero generate an INVALID_OPERATION error."
4518 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004519 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004520 {
Jamie Madill437fa652016-05-03 15:13:24 -04004521 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004522 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4523 return false;
4524 }
4525
Geoff Lang496c02d2016-10-20 11:38:11 -07004526 if (length)
4527 {
4528 *length = 1;
4529 }
4530
Olli Etuaho4f667482016-03-30 15:56:35 +03004531 return true;
4532}
4533
4534bool ValidateUnmapBufferBase(Context *context, GLenum target)
4535{
4536 if (!ValidBufferTarget(context, target))
4537 {
Jamie Madill437fa652016-05-03 15:13:24 -04004538 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004539 return false;
4540 }
4541
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004542 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004543
4544 if (buffer == nullptr || !buffer->isMapped())
4545 {
Jamie Madill437fa652016-05-03 15:13:24 -04004546 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004547 return false;
4548 }
4549
4550 return true;
4551}
4552
4553bool ValidateMapBufferRangeBase(Context *context,
4554 GLenum target,
4555 GLintptr offset,
4556 GLsizeiptr length,
4557 GLbitfield access)
4558{
4559 if (!ValidBufferTarget(context, target))
4560 {
Jamie Madill437fa652016-05-03 15:13:24 -04004561 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004562 return false;
4563 }
4564
4565 if (offset < 0 || length < 0)
4566 {
Jamie Madill437fa652016-05-03 15:13:24 -04004567 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004568 return false;
4569 }
4570
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004571 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004572
4573 if (!buffer)
4574 {
Jamie Madill437fa652016-05-03 15:13:24 -04004575 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004576 return false;
4577 }
4578
4579 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004580 CheckedNumeric<size_t> checkedOffset(offset);
4581 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004582
Jamie Madille2e406c2016-06-02 13:04:10 -04004583 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004584 {
Jamie Madill437fa652016-05-03 15:13:24 -04004585 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004586 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4587 return false;
4588 }
4589
4590 // Check for invalid bits in the mask
4591 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4592 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4593 GL_MAP_UNSYNCHRONIZED_BIT;
4594
4595 if (access & ~(allAccessBits))
4596 {
Jamie Madill437fa652016-05-03 15:13:24 -04004597 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004598 return false;
4599 }
4600
4601 if (length == 0)
4602 {
Jamie Madill437fa652016-05-03 15:13:24 -04004603 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004604 return false;
4605 }
4606
4607 if (buffer->isMapped())
4608 {
Jamie Madill437fa652016-05-03 15:13:24 -04004609 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004610 return false;
4611 }
4612
4613 // Check for invalid bit combinations
4614 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4615 {
Jamie Madill437fa652016-05-03 15:13:24 -04004616 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004617 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4618 return false;
4619 }
4620
4621 GLbitfield writeOnlyBits =
4622 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4623
4624 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4625 {
Jamie Madill437fa652016-05-03 15:13:24 -04004626 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004627 "Invalid access bits when mapping buffer for reading: 0x%X.",
4628 access));
4629 return false;
4630 }
4631
4632 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4633 {
Jamie Madill437fa652016-05-03 15:13:24 -04004634 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004635 GL_INVALID_OPERATION,
4636 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4637 return false;
4638 }
4639 return true;
4640}
4641
4642bool ValidateFlushMappedBufferRangeBase(Context *context,
4643 GLenum target,
4644 GLintptr offset,
4645 GLsizeiptr length)
4646{
4647 if (offset < 0 || length < 0)
4648 {
Jamie Madill437fa652016-05-03 15:13:24 -04004649 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004650 return false;
4651 }
4652
4653 if (!ValidBufferTarget(context, target))
4654 {
Jamie Madill437fa652016-05-03 15:13:24 -04004655 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004656 return false;
4657 }
4658
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004659 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004660
4661 if (buffer == nullptr)
4662 {
Jamie Madill437fa652016-05-03 15:13:24 -04004663 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004664 return false;
4665 }
4666
4667 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4668 {
Jamie Madill437fa652016-05-03 15:13:24 -04004669 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004670 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4671 return false;
4672 }
4673
4674 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004675 CheckedNumeric<size_t> checkedOffset(offset);
4676 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004677
Jamie Madille2e406c2016-06-02 13:04:10 -04004678 if (!checkedSize.IsValid() ||
4679 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004680 {
Jamie Madill437fa652016-05-03 15:13:24 -04004681 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004682 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4683 return false;
4684 }
4685
4686 return true;
4687}
4688
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004689bool ValidateGenerateMipmap(Context *context, GLenum target)
4690{
4691 if (!ValidTextureTarget(context, target))
4692 {
4693 context->handleError(Error(GL_INVALID_ENUM));
4694 return false;
4695 }
4696
4697 Texture *texture = context->getTargetTexture(target);
4698
4699 if (texture == nullptr)
4700 {
4701 context->handleError(Error(GL_INVALID_OPERATION));
4702 return false;
4703 }
4704
4705 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4706
4707 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4708 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4709 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4710 {
4711 context->handleError(Error(GL_INVALID_OPERATION));
4712 return false;
4713 }
4714
Jamie Madilla3944d42016-07-22 22:13:26 -04004715 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4716 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4717 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004718
4719 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4720 // unsized formats or that are color renderable and filterable. Since we do not track if
4721 // the texture was created with sized or unsized format (only sized formats are stored),
4722 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4723 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4724 // textures since they're the only texture format that can be created with unsized formats
4725 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4726 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004727 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4728 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004729 {
4730 context->handleError(Error(GL_INVALID_OPERATION));
4731 return false;
4732 }
4733
4734 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004735 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004736 {
4737 context->handleError(Error(GL_INVALID_OPERATION));
4738 return false;
4739 }
4740
4741 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004742 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004743 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4744 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4745 {
Geoff Lang55482a12016-11-21 16:54:01 -05004746 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004747 context->handleError(Error(GL_INVALID_OPERATION));
4748 return false;
4749 }
4750
4751 // Cube completeness check
4752 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4753 {
4754 context->handleError(Error(GL_INVALID_OPERATION));
4755 return false;
4756 }
4757
4758 return true;
4759}
4760
Olli Etuaho41997e72016-03-10 13:38:39 +02004761bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4762{
4763 return ValidateGenOrDelete(context, n);
4764}
4765
4766bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4767{
4768 return ValidateGenOrDelete(context, n);
4769}
4770
4771bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4772{
4773 return ValidateGenOrDelete(context, n);
4774}
4775
4776bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4777{
4778 return ValidateGenOrDelete(context, n);
4779}
4780
4781bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4782{
4783 return ValidateGenOrDelete(context, n);
4784}
4785
4786bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4787{
4788 return ValidateGenOrDelete(context, n);
4789}
4790
4791bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4792{
4793 return ValidateGenOrDelete(context, n);
4794}
4795
4796bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4797{
4798 return ValidateGenOrDelete(context, n);
4799}
4800
4801bool ValidateGenOrDelete(Context *context, GLint n)
4802{
4803 if (n < 0)
4804 {
Jamie Madill437fa652016-05-03 15:13:24 -04004805 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004806 return false;
4807 }
4808 return true;
4809}
4810
Geoff Langf41a7152016-09-19 15:11:17 -04004811bool ValidateEnable(Context *context, GLenum cap)
4812{
4813 if (!ValidCap(context, cap, false))
4814 {
4815 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4816 return false;
4817 }
4818
4819 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4820 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4821 {
4822 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4823 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4824
4825 // We also output an error message to the debugger window if tracing is active, so that
4826 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05004827 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04004828 return false;
4829 }
4830
4831 return true;
4832}
4833
4834bool ValidateDisable(Context *context, GLenum cap)
4835{
4836 if (!ValidCap(context, cap, false))
4837 {
4838 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4839 return false;
4840 }
4841
4842 return true;
4843}
4844
4845bool ValidateIsEnabled(Context *context, GLenum cap)
4846{
4847 if (!ValidCap(context, cap, true))
4848 {
4849 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4850 return false;
4851 }
4852
4853 return true;
4854}
4855
Geoff Langff5b2d52016-09-07 11:32:23 -04004856bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4857{
4858 if (!context->getExtensions().robustClientMemory)
4859 {
4860 context->handleError(
4861 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4862 return false;
4863 }
4864
4865 if (bufSize < 0)
4866 {
4867 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4868 return false;
4869 }
4870
4871 return true;
4872}
4873
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004874bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4875{
4876 if (bufSize < numParams)
4877 {
4878 context->handleError(Error(GL_INVALID_OPERATION,
4879 "%u parameters are required but %i were provided.", numParams,
4880 bufSize));
4881 return false;
4882 }
4883
4884 return true;
4885}
4886
Geoff Langff5b2d52016-09-07 11:32:23 -04004887bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4888 GLenum target,
4889 GLenum attachment,
4890 GLenum pname,
4891 GLsizei *numParams)
4892{
4893 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4894 *numParams = 1;
4895
4896 if (!ValidFramebufferTarget(target))
4897 {
4898 context->handleError(Error(GL_INVALID_ENUM));
4899 return false;
4900 }
4901
4902 int clientVersion = context->getClientMajorVersion();
4903
4904 switch (pname)
4905 {
4906 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4907 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4908 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4909 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4910 break;
4911
4912 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4913 if (clientVersion < 3 && !context->getExtensions().sRGB)
4914 {
4915 context->handleError(Error(GL_INVALID_ENUM));
4916 return false;
4917 }
4918 break;
4919
4920 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4921 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4922 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4923 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4924 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4925 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4926 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4927 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4928 if (clientVersion < 3)
4929 {
4930 context->handleError(Error(GL_INVALID_ENUM));
4931 return false;
4932 }
4933 break;
4934
4935 default:
4936 context->handleError(Error(GL_INVALID_ENUM));
4937 return false;
4938 }
4939
4940 // Determine if the attachment is a valid enum
4941 switch (attachment)
4942 {
4943 case GL_BACK:
4944 case GL_FRONT:
4945 case GL_DEPTH:
4946 case GL_STENCIL:
4947 case GL_DEPTH_STENCIL_ATTACHMENT:
4948 if (clientVersion < 3)
4949 {
4950 context->handleError(Error(GL_INVALID_ENUM));
4951 return false;
4952 }
4953 break;
4954
4955 case GL_DEPTH_ATTACHMENT:
4956 case GL_STENCIL_ATTACHMENT:
4957 break;
4958
4959 default:
4960 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4961 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4962 {
4963 context->handleError(Error(GL_INVALID_ENUM));
4964 return false;
4965 }
4966 break;
4967 }
4968
4969 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4970 ASSERT(framebuffer);
4971
4972 if (framebuffer->id() == 0)
4973 {
4974 if (clientVersion < 3)
4975 {
4976 context->handleError(Error(GL_INVALID_OPERATION));
4977 return false;
4978 }
4979
4980 switch (attachment)
4981 {
4982 case GL_BACK:
4983 case GL_DEPTH:
4984 case GL_STENCIL:
4985 break;
4986
4987 default:
4988 context->handleError(Error(GL_INVALID_OPERATION));
4989 return false;
4990 }
4991 }
4992 else
4993 {
4994 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4995 {
4996 // Valid attachment query
4997 }
4998 else
4999 {
5000 switch (attachment)
5001 {
5002 case GL_DEPTH_ATTACHMENT:
5003 case GL_STENCIL_ATTACHMENT:
5004 break;
5005
5006 case GL_DEPTH_STENCIL_ATTACHMENT:
5007 if (!framebuffer->hasValidDepthStencil())
5008 {
5009 context->handleError(Error(GL_INVALID_OPERATION));
5010 return false;
5011 }
5012 break;
5013
5014 default:
5015 context->handleError(Error(GL_INVALID_OPERATION));
5016 return false;
5017 }
5018 }
5019 }
5020
5021 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
5022 if (attachmentObject)
5023 {
5024 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
5025 attachmentObject->type() == GL_TEXTURE ||
5026 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
5027
5028 switch (pname)
5029 {
5030 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5031 if (attachmentObject->type() != GL_RENDERBUFFER &&
5032 attachmentObject->type() != GL_TEXTURE)
5033 {
5034 context->handleError(Error(GL_INVALID_ENUM));
5035 return false;
5036 }
5037 break;
5038
5039 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
5040 if (attachmentObject->type() != GL_TEXTURE)
5041 {
5042 context->handleError(Error(GL_INVALID_ENUM));
5043 return false;
5044 }
5045 break;
5046
5047 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
5048 if (attachmentObject->type() != GL_TEXTURE)
5049 {
5050 context->handleError(Error(GL_INVALID_ENUM));
5051 return false;
5052 }
5053 break;
5054
5055 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
5056 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
5057 {
5058 context->handleError(Error(GL_INVALID_OPERATION));
5059 return false;
5060 }
5061 break;
5062
5063 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
5064 if (attachmentObject->type() != GL_TEXTURE)
5065 {
5066 context->handleError(Error(GL_INVALID_ENUM));
5067 return false;
5068 }
5069 break;
5070
5071 default:
5072 break;
5073 }
5074 }
5075 else
5076 {
5077 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
5078 // is NONE, then querying any other pname will generate INVALID_ENUM.
5079
5080 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
5081 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
5082 // INVALID_OPERATION for all other pnames
5083
5084 switch (pname)
5085 {
5086 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5087 break;
5088
5089 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5090 if (clientVersion < 3)
5091 {
5092 context->handleError(Error(GL_INVALID_ENUM));
5093 return false;
5094 }
5095 break;
5096
5097 default:
5098 if (clientVersion < 3)
5099 {
5100 context->handleError(Error(GL_INVALID_ENUM));
5101 return false;
5102 }
5103 else
5104 {
5105 context->handleError(Error(GL_INVALID_OPERATION));
5106 return false;
5107 }
5108 }
5109 }
5110
5111 return true;
5112}
5113
5114bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5115 GLenum target,
5116 GLenum attachment,
5117 GLenum pname,
5118 GLsizei bufSize,
5119 GLsizei *numParams)
5120{
5121 if (!ValidateRobustEntryPoint(context, bufSize))
5122 {
5123 return false;
5124 }
5125
5126 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5127 {
5128 return false;
5129 }
5130
5131 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5132 {
5133 return false;
5134 }
5135
5136 return true;
5137}
5138
5139bool ValidateGetBufferParameteriv(ValidationContext *context,
5140 GLenum target,
5141 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005142 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005143{
Geoff Langebebe1c2016-10-14 12:01:31 -04005144 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005145}
5146
5147bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5148 GLenum target,
5149 GLenum pname,
5150 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005151 GLsizei *length,
5152 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005153{
5154 if (!ValidateRobustEntryPoint(context, bufSize))
5155 {
5156 return false;
5157 }
5158
Geoff Langebebe1c2016-10-14 12:01:31 -04005159 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005160 {
5161 return false;
5162 }
5163
Geoff Langebebe1c2016-10-14 12:01:31 -04005164 if (!ValidateRobustBufferSize(context, bufSize, *length))
5165 {
5166 return false;
5167 }
5168
5169 return true;
5170}
5171
5172bool ValidateGetBufferParameteri64v(ValidationContext *context,
5173 GLenum target,
5174 GLenum pname,
5175 GLint64 *params)
5176{
5177 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5178}
5179
5180bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5181 GLenum target,
5182 GLenum pname,
5183 GLsizei bufSize,
5184 GLsizei *length,
5185 GLint64 *params)
5186{
5187 if (!ValidateRobustEntryPoint(context, bufSize))
5188 {
5189 return false;
5190 }
5191
5192 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5193 {
5194 return false;
5195 }
5196
5197 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005198 {
5199 return false;
5200 }
5201
5202 return true;
5203}
5204
5205bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5206{
5207 // Currently, all GetProgramiv queries return 1 parameter
5208 *numParams = 1;
5209
5210 Program *programObject = GetValidProgram(context, program);
5211 if (!programObject)
5212 {
5213 return false;
5214 }
5215
5216 switch (pname)
5217 {
5218 case GL_DELETE_STATUS:
5219 case GL_LINK_STATUS:
5220 case GL_VALIDATE_STATUS:
5221 case GL_INFO_LOG_LENGTH:
5222 case GL_ATTACHED_SHADERS:
5223 case GL_ACTIVE_ATTRIBUTES:
5224 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5225 case GL_ACTIVE_UNIFORMS:
5226 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5227 break;
5228
5229 case GL_PROGRAM_BINARY_LENGTH:
5230 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5231 {
5232 context->handleError(Error(GL_INVALID_ENUM,
5233 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5234 "GL_OES_get_program_binary or ES 3.0."));
5235 return false;
5236 }
5237 break;
5238
5239 case GL_ACTIVE_UNIFORM_BLOCKS:
5240 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5241 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5242 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5243 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5244 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5245 if (context->getClientMajorVersion() < 3)
5246 {
5247 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5248 return false;
5249 }
5250 break;
5251
Yunchao He61afff12017-03-14 15:34:03 +08005252 case GL_PROGRAM_SEPARABLE:
5253 if (context->getClientVersion() < Version(3, 1))
5254 {
5255 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.1."));
5256 return false;
5257 }
5258 break;
5259
Geoff Langff5b2d52016-09-07 11:32:23 -04005260 default:
5261 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5262 return false;
5263 }
5264
5265 return true;
5266}
5267
5268bool ValidateGetProgramivRobustANGLE(Context *context,
5269 GLuint program,
5270 GLenum pname,
5271 GLsizei bufSize,
5272 GLsizei *numParams)
5273{
5274 if (!ValidateRobustEntryPoint(context, bufSize))
5275 {
5276 return false;
5277 }
5278
5279 if (!ValidateGetProgramiv(context, program, pname, numParams))
5280 {
5281 return false;
5282 }
5283
5284 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5285 {
5286 return false;
5287 }
5288
5289 return true;
5290}
5291
Geoff Lang740d9022016-10-07 11:20:52 -04005292bool ValidateGetRenderbufferParameteriv(Context *context,
5293 GLenum target,
5294 GLenum pname,
5295 GLint *params)
5296{
5297 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5298}
5299
5300bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5301 GLenum target,
5302 GLenum pname,
5303 GLsizei bufSize,
5304 GLsizei *length,
5305 GLint *params)
5306{
5307 if (!ValidateRobustEntryPoint(context, bufSize))
5308 {
5309 return false;
5310 }
5311
5312 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5313 {
5314 return false;
5315 }
5316
5317 if (!ValidateRobustBufferSize(context, bufSize, *length))
5318 {
5319 return false;
5320 }
5321
5322 return true;
5323}
5324
Geoff Langd7d0ed32016-10-07 11:33:51 -04005325bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5326{
5327 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5328}
5329
5330bool ValidateGetShaderivRobustANGLE(Context *context,
5331 GLuint shader,
5332 GLenum pname,
5333 GLsizei bufSize,
5334 GLsizei *length,
5335 GLint *params)
5336{
5337 if (!ValidateRobustEntryPoint(context, bufSize))
5338 {
5339 return false;
5340 }
5341
5342 if (!ValidateGetShaderivBase(context, shader, pname, length))
5343 {
5344 return false;
5345 }
5346
5347 if (!ValidateRobustBufferSize(context, bufSize, *length))
5348 {
5349 return false;
5350 }
5351
5352 return true;
5353}
5354
Geoff Langc1984ed2016-10-07 12:41:00 -04005355bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5356{
5357 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5358}
5359
5360bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5361 GLenum target,
5362 GLenum pname,
5363 GLsizei bufSize,
5364 GLsizei *length,
5365 GLfloat *params)
5366{
5367 if (!ValidateRobustEntryPoint(context, bufSize))
5368 {
5369 return false;
5370 }
5371
5372 if (!ValidateGetTexParameterBase(context, target, pname, length))
5373 {
5374 return false;
5375 }
5376
5377 if (!ValidateRobustBufferSize(context, bufSize, *length))
5378 {
5379 return false;
5380 }
5381
5382 return true;
5383}
5384
5385bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5386{
5387 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5388}
5389
5390bool ValidateGetTexParameterivRobustANGLE(Context *context,
5391 GLenum target,
5392 GLenum pname,
5393 GLsizei bufSize,
5394 GLsizei *length,
5395 GLint *params)
5396{
5397 if (!ValidateRobustEntryPoint(context, bufSize))
5398 {
5399 return false;
5400 }
5401
5402 if (!ValidateGetTexParameterBase(context, target, pname, length))
5403 {
5404 return false;
5405 }
5406
5407 if (!ValidateRobustBufferSize(context, bufSize, *length))
5408 {
5409 return false;
5410 }
5411
5412 return true;
5413}
5414
5415bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5416{
5417 return ValidateTexParameterBase(context, target, pname, -1, &param);
5418}
5419
5420bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5421{
5422 return ValidateTexParameterBase(context, target, pname, -1, params);
5423}
5424
5425bool ValidateTexParameterfvRobustANGLE(Context *context,
5426 GLenum target,
5427 GLenum pname,
5428 GLsizei bufSize,
5429 const GLfloat *params)
5430{
5431 if (!ValidateRobustEntryPoint(context, bufSize))
5432 {
5433 return false;
5434 }
5435
5436 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5437}
5438
5439bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5440{
5441 return ValidateTexParameterBase(context, target, pname, -1, &param);
5442}
5443
5444bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5445{
5446 return ValidateTexParameterBase(context, target, pname, -1, params);
5447}
5448
5449bool ValidateTexParameterivRobustANGLE(Context *context,
5450 GLenum target,
5451 GLenum pname,
5452 GLsizei bufSize,
5453 const GLint *params)
5454{
5455 if (!ValidateRobustEntryPoint(context, bufSize))
5456 {
5457 return false;
5458 }
5459
5460 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5461}
5462
5463bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5464{
5465 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5466}
5467
5468bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5469 GLuint sampler,
5470 GLenum pname,
5471 GLuint bufSize,
5472 GLsizei *length,
5473 GLfloat *params)
5474{
5475 if (!ValidateRobustEntryPoint(context, bufSize))
5476 {
5477 return false;
5478 }
5479
5480 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5481 {
5482 return false;
5483 }
5484
5485 if (!ValidateRobustBufferSize(context, bufSize, *length))
5486 {
5487 return false;
5488 }
5489
5490 return true;
5491}
5492
5493bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5494{
5495 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5496}
5497
5498bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5499 GLuint sampler,
5500 GLenum pname,
5501 GLuint bufSize,
5502 GLsizei *length,
5503 GLint *params)
5504{
5505 if (!ValidateRobustEntryPoint(context, bufSize))
5506 {
5507 return false;
5508 }
5509
5510 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5511 {
5512 return false;
5513 }
5514
5515 if (!ValidateRobustBufferSize(context, bufSize, *length))
5516 {
5517 return false;
5518 }
5519
5520 return true;
5521}
5522
5523bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5524{
5525 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5526}
5527
5528bool ValidateSamplerParameterfv(Context *context,
5529 GLuint sampler,
5530 GLenum pname,
5531 const GLfloat *params)
5532{
5533 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5534}
5535
5536bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5537 GLuint sampler,
5538 GLenum pname,
5539 GLsizei bufSize,
5540 const GLfloat *params)
5541{
5542 if (!ValidateRobustEntryPoint(context, bufSize))
5543 {
5544 return false;
5545 }
5546
5547 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5548}
5549
5550bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5551{
5552 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5553}
5554
5555bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5556{
5557 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5558}
5559
5560bool ValidateSamplerParameterivRobustANGLE(Context *context,
5561 GLuint sampler,
5562 GLenum pname,
5563 GLsizei bufSize,
5564 const GLint *params)
5565{
5566 if (!ValidateRobustEntryPoint(context, bufSize))
5567 {
5568 return false;
5569 }
5570
5571 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5572}
5573
Geoff Lang0b031062016-10-13 14:30:04 -04005574bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5575{
5576 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5577}
5578
5579bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5580 GLuint index,
5581 GLenum pname,
5582 GLsizei bufSize,
5583 GLsizei *length,
5584 GLfloat *params)
5585{
5586 if (!ValidateRobustEntryPoint(context, bufSize))
5587 {
5588 return false;
5589 }
5590
5591 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5592 {
5593 return false;
5594 }
5595
5596 if (!ValidateRobustBufferSize(context, bufSize, *length))
5597 {
5598 return false;
5599 }
5600
5601 return true;
5602}
5603
5604bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5605{
5606 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5607}
5608
5609bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5610 GLuint index,
5611 GLenum pname,
5612 GLsizei bufSize,
5613 GLsizei *length,
5614 GLint *params)
5615{
5616 if (!ValidateRobustEntryPoint(context, bufSize))
5617 {
5618 return false;
5619 }
5620
5621 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5622 {
5623 return false;
5624 }
5625
5626 if (!ValidateRobustBufferSize(context, bufSize, *length))
5627 {
5628 return false;
5629 }
5630
5631 return true;
5632}
5633
5634bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5635{
5636 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5637}
5638
5639bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5640 GLuint index,
5641 GLenum pname,
5642 GLsizei bufSize,
5643 GLsizei *length,
5644 void **pointer)
5645{
5646 if (!ValidateRobustEntryPoint(context, bufSize))
5647 {
5648 return false;
5649 }
5650
5651 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5652 {
5653 return false;
5654 }
5655
5656 if (!ValidateRobustBufferSize(context, bufSize, *length))
5657 {
5658 return false;
5659 }
5660
5661 return true;
5662}
5663
5664bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5665{
5666 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5667}
5668
5669bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5670 GLuint index,
5671 GLenum pname,
5672 GLsizei bufSize,
5673 GLsizei *length,
5674 GLint *params)
5675{
5676 if (!ValidateRobustEntryPoint(context, bufSize))
5677 {
5678 return false;
5679 }
5680
5681 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5682 {
5683 return false;
5684 }
5685
5686 if (!ValidateRobustBufferSize(context, bufSize, *length))
5687 {
5688 return false;
5689 }
5690
5691 return true;
5692}
5693
5694bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5695{
5696 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5697}
5698
5699bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5700 GLuint index,
5701 GLenum pname,
5702 GLsizei bufSize,
5703 GLsizei *length,
5704 GLuint *params)
5705{
5706 if (!ValidateRobustEntryPoint(context, bufSize))
5707 {
5708 return false;
5709 }
5710
5711 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5712 {
5713 return false;
5714 }
5715
5716 if (!ValidateRobustBufferSize(context, bufSize, *length))
5717 {
5718 return false;
5719 }
5720
5721 return true;
5722}
5723
Geoff Lang6899b872016-10-14 11:30:13 -04005724bool ValidateGetActiveUniformBlockiv(Context *context,
5725 GLuint program,
5726 GLuint uniformBlockIndex,
5727 GLenum pname,
5728 GLint *params)
5729{
5730 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5731}
5732
5733bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5734 GLuint program,
5735 GLuint uniformBlockIndex,
5736 GLenum pname,
5737 GLsizei bufSize,
5738 GLsizei *length,
5739 GLint *params)
5740{
5741 if (!ValidateRobustEntryPoint(context, bufSize))
5742 {
5743 return false;
5744 }
5745
5746 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5747 {
5748 return false;
5749 }
5750
5751 if (!ValidateRobustBufferSize(context, bufSize, *length))
5752 {
5753 return false;
5754 }
5755
5756 return true;
5757}
5758
Geoff Lang0a9661f2016-10-20 10:59:20 -07005759bool ValidateGetInternalFormativ(Context *context,
5760 GLenum target,
5761 GLenum internalformat,
5762 GLenum pname,
5763 GLsizei bufSize,
5764 GLint *params)
5765{
5766 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5767 nullptr);
5768}
5769
5770bool ValidateGetInternalFormativRobustANGLE(Context *context,
5771 GLenum target,
5772 GLenum internalformat,
5773 GLenum pname,
5774 GLsizei bufSize,
5775 GLsizei *length,
5776 GLint *params)
5777{
5778 if (!ValidateRobustEntryPoint(context, bufSize))
5779 {
5780 return false;
5781 }
5782
5783 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5784 {
5785 return false;
5786 }
5787
5788 if (!ValidateRobustBufferSize(context, bufSize, *length))
5789 {
5790 return false;
5791 }
5792
5793 return true;
5794}
5795
Shao80957d92017-02-20 21:25:59 +08005796bool ValidateVertexFormatBase(ValidationContext *context,
5797 GLuint attribIndex,
5798 GLint size,
5799 GLenum type,
5800 GLboolean pureInteger)
5801{
5802 const Caps &caps = context->getCaps();
5803 if (attribIndex >= caps.maxVertexAttributes)
5804 {
5805 context->handleError(
5806 Error(GL_INVALID_VALUE, "attribindex must be smaller than MAX_VERTEX_ATTRIBS."));
5807 return false;
5808 }
5809
5810 if (size < 1 || size > 4)
5811 {
5812 context->handleError(Error(GL_INVALID_VALUE, "size must be between one and four."));
5813 }
5814
5815 switch (type)
5816 {
5817 case GL_BYTE:
5818 case GL_UNSIGNED_BYTE:
5819 case GL_SHORT:
5820 case GL_UNSIGNED_SHORT:
5821 break;
5822
5823 case GL_INT:
5824 case GL_UNSIGNED_INT:
5825 if (context->getClientMajorVersion() < 3)
5826 {
5827 context->handleError(
5828 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
5829 return false;
5830 }
5831 break;
5832
5833 case GL_FIXED:
5834 case GL_FLOAT:
5835 if (pureInteger)
5836 {
5837 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
5838 return false;
5839 }
5840 break;
5841
5842 case GL_HALF_FLOAT:
5843 if (context->getClientMajorVersion() < 3)
5844 {
5845 context->handleError(
5846 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
5847 return false;
5848 }
5849 if (pureInteger)
5850 {
5851 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
5852 return false;
5853 }
5854 break;
5855
5856 case GL_INT_2_10_10_10_REV:
5857 case GL_UNSIGNED_INT_2_10_10_10_REV:
5858 if (context->getClientMajorVersion() < 3)
5859 {
5860 context->handleError(
5861 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
5862 return false;
5863 }
5864 if (pureInteger)
5865 {
5866 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
5867 return false;
5868 }
5869 if (size != 4)
5870 {
5871 context->handleError(Error(GL_INVALID_OPERATION,
5872 "Type is INT_2_10_10_10_REV or "
5873 "UNSIGNED_INT_2_10_10_10_REV and size is not 4."));
5874 return false;
5875 }
5876 break;
5877
5878 default:
5879 context->handleError(Error(GL_INVALID_ENUM, "Invalid vertex type."));
5880 return false;
5881 }
5882
5883 return true;
5884}
5885
Jamie Madillc29968b2016-01-20 11:17:23 -05005886} // namespace gl