blob: 64ad879ebd1fe763ad0b1fa0dc0eabdca4512874 [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,
Geoff Lange93daba2017-03-30 13:54:40 -0400236 GLsizei *columns,
237 GLsizei *rows,
Geoff Lang62fce5b2016-09-30 10:46:35 -0400238 GLvoid *pixels)
239{
240 if (length != nullptr)
241 {
242 *length = 0;
243 }
Geoff Lange93daba2017-03-30 13:54:40 -0400244 if (rows != nullptr)
245 {
246 *rows = 0;
247 }
248 if (columns != nullptr)
249 {
250 *columns = 0;
251 }
Geoff Lang62fce5b2016-09-30 10:46:35 -0400252
253 if (width < 0 || height < 0)
254 {
255 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
256 return false;
257 }
258
259 auto readFramebuffer = context->getGLState().getReadFramebuffer();
260
261 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
262 {
263 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
264 return false;
265 }
266
267 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
268 {
269 context->handleError(Error(GL_INVALID_OPERATION));
270 return false;
271 }
272
273 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
274 ASSERT(framebuffer);
275
276 if (framebuffer->getReadBufferState() == GL_NONE)
277 {
278 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
279 return false;
280 }
281
282 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500283 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
284 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
285 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
286 // situation is an application error that would lead to a crash in ANGLE.
287 if (readBuffer == nullptr)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400288 {
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500289 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
Geoff Lang62fce5b2016-09-30 10:46:35 -0400290 return false;
291 }
292
293 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
294 GLenum currentType = framebuffer->getImplementationColorReadType();
295 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
296
297 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
298 bool validFormatTypeCombination =
299 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
300
301 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
302 {
303 context->handleError(Error(GL_INVALID_OPERATION));
304 return false;
305 }
306
307 // Check for pixel pack buffer related API errors
308 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
309 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
310 {
311 // ...the buffer object's data store is currently mapped.
312 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
313 return false;
314 }
315
316 // .. the data would be packed to the buffer object such that the memory writes required
317 // would exceed the data store size.
318 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
319 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
320 const gl::Extents size(width, height, 1);
321 const auto &pack = context->getGLState().getPackState();
322
323 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
324 if (endByteOrErr.isError())
325 {
326 context->handleError(endByteOrErr.getError());
327 return false;
328 }
329
330 size_t endByte = endByteOrErr.getResult();
331 if (bufSize >= 0)
332 {
Geoff Lange93daba2017-03-30 13:54:40 -0400333 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400334 {
335 context->handleError(
336 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
337 return false;
338 }
339 }
340
341 if (pixelPackBuffer != nullptr)
342 {
343 CheckedNumeric<size_t> checkedEndByte(endByte);
344 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
345 checkedEndByte += checkedOffset;
346
347 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
348 {
349 // Overflow past the end of the buffer
350 context->handleError(
351 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
352 return false;
353 }
354 }
355
Geoff Lange93daba2017-03-30 13:54:40 -0400356 if (pixelPackBuffer == nullptr && length != nullptr)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400357 {
358 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
359 {
360 context->handleError(
361 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
362 return false;
363 }
364
365 *length = static_cast<GLsizei>(endByte);
366 }
367
Geoff Lange93daba2017-03-30 13:54:40 -0400368 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
369 angle::CheckedNumeric<int> clippedExtent(length);
370 if (start < 0)
371 {
372 // "subtract" the area that is less than 0
373 clippedExtent += start;
374 }
375
376 const int readExtent = start + length;
377 if (readExtent > bufferSize)
378 {
379 // Subtract the region to the right of the read buffer
380 clippedExtent -= (readExtent - bufferSize);
381 }
382
383 if (!clippedExtent.IsValid())
384 {
385 return 0;
386 }
387
388 return std::max(clippedExtent.ValueOrDie(), 0);
389 };
390
391 if (columns != nullptr)
392 {
393 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
394 }
395
396 if (rows != nullptr)
397 {
398 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
399 }
400
Geoff Lang62fce5b2016-09-30 10:46:35 -0400401 return true;
402}
403
Geoff Lang740d9022016-10-07 11:20:52 -0400404bool ValidateGetRenderbufferParameterivBase(Context *context,
405 GLenum target,
406 GLenum pname,
407 GLsizei *length)
408{
409 if (length)
410 {
411 *length = 0;
412 }
413
414 if (target != GL_RENDERBUFFER)
415 {
416 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
417 return false;
418 }
419
420 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
421 if (renderbuffer == nullptr)
422 {
423 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
424 return false;
425 }
426
427 switch (pname)
428 {
429 case GL_RENDERBUFFER_WIDTH:
430 case GL_RENDERBUFFER_HEIGHT:
431 case GL_RENDERBUFFER_INTERNAL_FORMAT:
432 case GL_RENDERBUFFER_RED_SIZE:
433 case GL_RENDERBUFFER_GREEN_SIZE:
434 case GL_RENDERBUFFER_BLUE_SIZE:
435 case GL_RENDERBUFFER_ALPHA_SIZE:
436 case GL_RENDERBUFFER_DEPTH_SIZE:
437 case GL_RENDERBUFFER_STENCIL_SIZE:
438 break;
439
440 case GL_RENDERBUFFER_SAMPLES_ANGLE:
441 if (!context->getExtensions().framebufferMultisample)
442 {
443 context->handleError(
444 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample 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 Langd7d0ed32016-10-07 11:33:51 -0400461bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
462{
463 if (length)
464 {
465 *length = 0;
466 }
467
468 if (GetValidShader(context, shader) == nullptr)
469 {
470 return false;
471 }
472
473 switch (pname)
474 {
475 case GL_SHADER_TYPE:
476 case GL_DELETE_STATUS:
477 case GL_COMPILE_STATUS:
478 case GL_INFO_LOG_LENGTH:
479 case GL_SHADER_SOURCE_LENGTH:
480 break;
481
482 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
483 if (!context->getExtensions().translatedShaderSource)
484 {
485 context->handleError(
486 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
487 return false;
488 }
489 break;
490
491 default:
492 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
493 return false;
494 }
495
496 if (length)
497 {
498 *length = 1;
499 }
500 return true;
501}
502
Geoff Langc1984ed2016-10-07 12:41:00 -0400503bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
504{
505 if (length)
506 {
507 *length = 0;
508 }
509
510 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
511 {
512 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
513 return false;
514 }
515
516 if (context->getTargetTexture(target) == nullptr)
517 {
518 // Should only be possible for external textures
519 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
520 return false;
521 }
522
523 switch (pname)
524 {
525 case GL_TEXTURE_MAG_FILTER:
526 case GL_TEXTURE_MIN_FILTER:
527 case GL_TEXTURE_WRAP_S:
528 case GL_TEXTURE_WRAP_T:
529 break;
530
531 case GL_TEXTURE_USAGE_ANGLE:
532 if (!context->getExtensions().textureUsage)
533 {
534 context->handleError(
535 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
536 return false;
537 }
538 break;
539
540 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
541 if (!context->getExtensions().textureFilterAnisotropic)
542 {
543 context->handleError(
544 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
545 return false;
546 }
547 break;
548
549 case GL_TEXTURE_IMMUTABLE_FORMAT:
550 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
551 {
552 context->handleError(
553 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
554 return false;
555 }
556 break;
557
558 case GL_TEXTURE_WRAP_R:
559 case GL_TEXTURE_IMMUTABLE_LEVELS:
560 case GL_TEXTURE_SWIZZLE_R:
561 case GL_TEXTURE_SWIZZLE_G:
562 case GL_TEXTURE_SWIZZLE_B:
563 case GL_TEXTURE_SWIZZLE_A:
564 case GL_TEXTURE_BASE_LEVEL:
565 case GL_TEXTURE_MAX_LEVEL:
566 case GL_TEXTURE_MIN_LOD:
567 case GL_TEXTURE_MAX_LOD:
568 case GL_TEXTURE_COMPARE_MODE:
569 case GL_TEXTURE_COMPARE_FUNC:
570 if (context->getClientMajorVersion() < 3)
571 {
572 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
573 return false;
574 }
575 break;
576
Geoff Lang81c6b572016-10-19 14:07:52 -0700577 case GL_TEXTURE_SRGB_DECODE_EXT:
578 if (!context->getExtensions().textureSRGBDecode)
579 {
580 context->handleError(
581 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
582 return false;
583 }
584 break;
585
Geoff Langc1984ed2016-10-07 12:41:00 -0400586 default:
587 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
588 return false;
589 }
590
591 if (length)
592 {
593 *length = 1;
594 }
595 return true;
596}
597
598template <typename ParamType>
599bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
600{
601 switch (ConvertToGLenum(params[0]))
602 {
603 case GL_CLAMP_TO_EDGE:
604 break;
605
606 case GL_REPEAT:
607 case GL_MIRRORED_REPEAT:
608 if (isExternalTextureTarget)
609 {
610 // OES_EGL_image_external specifies this error.
611 context->handleError(Error(
612 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
613 return false;
614 }
615 break;
616
617 default:
618 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
619 return false;
620 }
621
622 return true;
623}
624
625template <typename ParamType>
626bool ValidateTextureMinFilterValue(Context *context,
627 ParamType *params,
628 bool isExternalTextureTarget)
629{
630 switch (ConvertToGLenum(params[0]))
631 {
632 case GL_NEAREST:
633 case GL_LINEAR:
634 break;
635
636 case GL_NEAREST_MIPMAP_NEAREST:
637 case GL_LINEAR_MIPMAP_NEAREST:
638 case GL_NEAREST_MIPMAP_LINEAR:
639 case GL_LINEAR_MIPMAP_LINEAR:
640 if (isExternalTextureTarget)
641 {
642 // OES_EGL_image_external specifies this error.
643 context->handleError(
644 Error(GL_INVALID_ENUM,
645 "external textures only support NEAREST and LINEAR filtering"));
646 return false;
647 }
648 break;
649
650 default:
651 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
652 return false;
653 }
654
655 return true;
656}
657
658template <typename ParamType>
659bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
660{
661 switch (ConvertToGLenum(params[0]))
662 {
663 case GL_NEAREST:
664 case GL_LINEAR:
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>
676bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
677{
678 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
679 switch (ConvertToGLenum(params[0]))
680 {
681 case GL_NONE:
682 case GL_COMPARE_REF_TO_TEXTURE:
683 break;
684
685 default:
686 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
687 return false;
688 }
689
690 return true;
691}
692
693template <typename ParamType>
694bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
695{
696 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
697 switch (ConvertToGLenum(params[0]))
698 {
699 case GL_LEQUAL:
700 case GL_GEQUAL:
701 case GL_LESS:
702 case GL_GREATER:
703 case GL_EQUAL:
704 case GL_NOTEQUAL:
705 case GL_ALWAYS:
706 case GL_NEVER:
707 break;
708
709 default:
710 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
711 return false;
712 }
713
714 return true;
715}
716
717template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700718bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
719{
720 if (!context->getExtensions().textureSRGBDecode)
721 {
722 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
723 return false;
724 }
725
726 switch (ConvertToGLenum(params[0]))
727 {
728 case GL_DECODE_EXT:
729 case GL_SKIP_DECODE_EXT:
730 break;
731
732 default:
733 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
734 return false;
735 }
736
737 return true;
738}
739
740template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400741bool ValidateTexParameterBase(Context *context,
742 GLenum target,
743 GLenum pname,
744 GLsizei bufSize,
745 ParamType *params)
746{
747 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
748 {
749 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
750 return false;
751 }
752
753 if (context->getTargetTexture(target) == nullptr)
754 {
755 // Should only be possible for external textures
756 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
757 return false;
758 }
759
760 const GLsizei minBufSize = 1;
761 if (bufSize >= 0 && bufSize < minBufSize)
762 {
763 context->handleError(
764 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
765 return false;
766 }
767
768 switch (pname)
769 {
770 case GL_TEXTURE_WRAP_R:
771 case GL_TEXTURE_SWIZZLE_R:
772 case GL_TEXTURE_SWIZZLE_G:
773 case GL_TEXTURE_SWIZZLE_B:
774 case GL_TEXTURE_SWIZZLE_A:
775 case GL_TEXTURE_BASE_LEVEL:
776 case GL_TEXTURE_MAX_LEVEL:
777 case GL_TEXTURE_COMPARE_MODE:
778 case GL_TEXTURE_COMPARE_FUNC:
779 case GL_TEXTURE_MIN_LOD:
780 case GL_TEXTURE_MAX_LOD:
781 if (context->getClientMajorVersion() < 3)
782 {
783 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
784 return false;
785 }
786 if (target == GL_TEXTURE_EXTERNAL_OES &&
787 !context->getExtensions().eglImageExternalEssl3)
788 {
789 context->handleError(Error(GL_INVALID_ENUM,
790 "ES3 texture parameters are not available without "
791 "GL_OES_EGL_image_external_essl3."));
792 return false;
793 }
794 break;
795
796 default:
797 break;
798 }
799
800 switch (pname)
801 {
802 case GL_TEXTURE_WRAP_S:
803 case GL_TEXTURE_WRAP_T:
804 case GL_TEXTURE_WRAP_R:
805 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
806 {
807 return false;
808 }
809 break;
810
811 case GL_TEXTURE_MIN_FILTER:
812 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
813 {
814 return false;
815 }
816 break;
817
818 case GL_TEXTURE_MAG_FILTER:
819 if (!ValidateTextureMagFilterValue(context, params))
820 {
821 return false;
822 }
823 break;
824
825 case GL_TEXTURE_USAGE_ANGLE:
826 switch (ConvertToGLenum(params[0]))
827 {
828 case GL_NONE:
829 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
830 break;
831
832 default:
833 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
834 return false;
835 }
836 break;
837
838 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
839 if (!context->getExtensions().textureFilterAnisotropic)
840 {
841 context->handleError(
842 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
843 return false;
844 }
845
846 // we assume the parameter passed to this validation method is truncated, not rounded
847 if (params[0] < 1)
848 {
849 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
850 return false;
851 }
852 break;
853
854 case GL_TEXTURE_MIN_LOD:
855 case GL_TEXTURE_MAX_LOD:
856 // any value is permissible
857 break;
858
859 case GL_TEXTURE_COMPARE_MODE:
860 if (!ValidateTextureCompareModeValue(context, params))
861 {
862 return false;
863 }
864 break;
865
866 case GL_TEXTURE_COMPARE_FUNC:
867 if (!ValidateTextureCompareFuncValue(context, params))
868 {
869 return false;
870 }
871 break;
872
873 case GL_TEXTURE_SWIZZLE_R:
874 case GL_TEXTURE_SWIZZLE_G:
875 case GL_TEXTURE_SWIZZLE_B:
876 case GL_TEXTURE_SWIZZLE_A:
877 switch (ConvertToGLenum(params[0]))
878 {
879 case GL_RED:
880 case GL_GREEN:
881 case GL_BLUE:
882 case GL_ALPHA:
883 case GL_ZERO:
884 case GL_ONE:
885 break;
886
887 default:
888 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
889 return false;
890 }
891 break;
892
893 case GL_TEXTURE_BASE_LEVEL:
894 if (params[0] < 0)
895 {
896 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
897 return false;
898 }
899 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
900 {
901 context->handleError(
902 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
903 return false;
904 }
905 break;
906
907 case GL_TEXTURE_MAX_LEVEL:
908 if (params[0] < 0)
909 {
910 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
911 return false;
912 }
913 break;
914
Geoff Lang3b573612016-10-31 14:08:10 -0400915 case GL_DEPTH_STENCIL_TEXTURE_MODE:
916 if (context->getClientVersion() < Version(3, 1))
917 {
918 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
919 return false;
920 }
Geoff Lang9f090372016-12-02 10:20:43 -0500921 switch (ConvertToGLenum(params[0]))
922 {
923 case GL_DEPTH_COMPONENT:
924 case GL_STENCIL_INDEX:
925 break;
926
927 default:
928 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
929 return false;
930 }
Geoff Lang3b573612016-10-31 14:08:10 -0400931 break;
932
Geoff Lang81c6b572016-10-19 14:07:52 -0700933 case GL_TEXTURE_SRGB_DECODE_EXT:
934 if (!ValidateTextureSRGBDecodeValue(context, params))
935 {
936 return false;
937 }
938 break;
939
Geoff Langc1984ed2016-10-07 12:41:00 -0400940 default:
941 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
942 return false;
943 }
944
945 return true;
946}
947
948template <typename ParamType>
949bool ValidateSamplerParameterBase(Context *context,
950 GLuint sampler,
951 GLenum pname,
952 GLsizei bufSize,
953 ParamType *params)
954{
955 if (context->getClientMajorVersion() < 3)
956 {
957 context->handleError(
958 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
959 return false;
960 }
961
962 if (!context->isSampler(sampler))
963 {
964 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
965 return false;
966 }
967
968 const GLsizei minBufSize = 1;
969 if (bufSize >= 0 && bufSize < minBufSize)
970 {
971 context->handleError(
972 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
973 return false;
974 }
975
976 switch (pname)
977 {
978 case GL_TEXTURE_WRAP_S:
979 case GL_TEXTURE_WRAP_T:
980 case GL_TEXTURE_WRAP_R:
981 if (!ValidateTextureWrapModeValue(context, params, false))
982 {
983 return false;
984 }
985 break;
986
987 case GL_TEXTURE_MIN_FILTER:
988 if (!ValidateTextureMinFilterValue(context, params, false))
989 {
990 return false;
991 }
992 break;
993
994 case GL_TEXTURE_MAG_FILTER:
995 if (!ValidateTextureMagFilterValue(context, params))
996 {
997 return false;
998 }
999 break;
1000
1001 case GL_TEXTURE_MIN_LOD:
1002 case GL_TEXTURE_MAX_LOD:
1003 // any value is permissible
1004 break;
1005
1006 case GL_TEXTURE_COMPARE_MODE:
1007 if (!ValidateTextureCompareModeValue(context, params))
1008 {
1009 return false;
1010 }
1011 break;
1012
1013 case GL_TEXTURE_COMPARE_FUNC:
1014 if (!ValidateTextureCompareFuncValue(context, params))
1015 {
1016 return false;
1017 }
1018 break;
1019
Geoff Lang81c6b572016-10-19 14:07:52 -07001020 case GL_TEXTURE_SRGB_DECODE_EXT:
1021 if (!ValidateTextureSRGBDecodeValue(context, params))
1022 {
1023 return false;
1024 }
1025 break;
1026
Geoff Langc1984ed2016-10-07 12:41:00 -04001027 default:
1028 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1029 return false;
1030 }
1031
1032 return true;
1033}
1034
1035bool ValidateGetSamplerParameterBase(Context *context,
1036 GLuint sampler,
1037 GLenum pname,
1038 GLsizei *length)
1039{
1040 if (length)
1041 {
1042 *length = 0;
1043 }
1044
1045 if (context->getClientMajorVersion() < 3)
1046 {
1047 context->handleError(
1048 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1049 return false;
1050 }
1051
1052 if (!context->isSampler(sampler))
1053 {
1054 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
1055 return false;
1056 }
1057
1058 switch (pname)
1059 {
1060 case GL_TEXTURE_WRAP_S:
1061 case GL_TEXTURE_WRAP_T:
1062 case GL_TEXTURE_WRAP_R:
1063 case GL_TEXTURE_MIN_FILTER:
1064 case GL_TEXTURE_MAG_FILTER:
1065 case GL_TEXTURE_MIN_LOD:
1066 case GL_TEXTURE_MAX_LOD:
1067 case GL_TEXTURE_COMPARE_MODE:
1068 case GL_TEXTURE_COMPARE_FUNC:
1069 break;
1070
Geoff Lang81c6b572016-10-19 14:07:52 -07001071 case GL_TEXTURE_SRGB_DECODE_EXT:
1072 if (!context->getExtensions().textureSRGBDecode)
1073 {
1074 context->handleError(
1075 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
1076 return false;
1077 }
1078 break;
1079
Geoff Langc1984ed2016-10-07 12:41:00 -04001080 default:
1081 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1082 return false;
1083 }
1084
1085 if (length)
1086 {
1087 *length = 1;
1088 }
1089 return true;
1090}
1091
Geoff Lang0b031062016-10-13 14:30:04 -04001092bool ValidateGetVertexAttribBase(Context *context,
1093 GLuint index,
1094 GLenum pname,
1095 GLsizei *length,
1096 bool pointer,
1097 bool pureIntegerEntryPoint)
1098{
1099 if (length)
1100 {
1101 *length = 0;
1102 }
1103
1104 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1105 {
1106 context->handleError(
1107 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1108 return false;
1109 }
1110
1111 if (index >= context->getCaps().maxVertexAttributes)
1112 {
1113 context->handleError(Error(
1114 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1115 return false;
1116 }
1117
1118 if (pointer)
1119 {
1120 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1121 {
1122 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1123 return false;
1124 }
1125 }
1126 else
1127 {
1128 switch (pname)
1129 {
1130 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1131 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1132 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1133 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1134 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1135 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1136 case GL_CURRENT_VERTEX_ATTRIB:
1137 break;
1138
1139 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1140 static_assert(
1141 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1142 "ANGLE extension enums not equal to GL enums.");
1143 if (context->getClientMajorVersion() < 3 &&
1144 !context->getExtensions().instancedArrays)
1145 {
1146 context->handleError(Error(GL_INVALID_ENUM,
1147 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1148 "3.0 or GL_ANGLE_instanced_arrays."));
1149 return false;
1150 }
1151 break;
1152
1153 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1154 if (context->getClientMajorVersion() < 3)
1155 {
Shao80957d92017-02-20 21:25:59 +08001156 context->handleError(Error(
1157 GL_INVALID_ENUM, "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0."));
1158 return false;
1159 }
1160 break;
1161
1162 case GL_VERTEX_ATTRIB_BINDING:
1163 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
1164 if (context->getClientVersion() < ES_3_1)
1165 {
1166 context->handleError(
1167 Error(GL_INVALID_ENUM, "Vertex Attrib Bindings require OpenGL ES 3.1."));
Geoff Lang0b031062016-10-13 14:30:04 -04001168 return false;
1169 }
1170 break;
1171
1172 default:
1173 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1174 return false;
1175 }
1176 }
1177
1178 if (length)
1179 {
1180 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1181 {
1182 *length = 4;
1183 }
1184 else
1185 {
1186 *length = 1;
1187 }
1188 }
1189
1190 return true;
1191}
1192
Geoff Lang6899b872016-10-14 11:30:13 -04001193bool ValidateGetActiveUniformBlockivBase(Context *context,
1194 GLuint program,
1195 GLuint uniformBlockIndex,
1196 GLenum pname,
1197 GLsizei *length)
1198{
1199 if (length)
1200 {
1201 *length = 0;
1202 }
1203
1204 if (context->getClientMajorVersion() < 3)
1205 {
1206 context->handleError(
1207 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1208 return false;
1209 }
1210
1211 Program *programObject = GetValidProgram(context, program);
1212 if (!programObject)
1213 {
1214 return false;
1215 }
1216
1217 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1218 {
1219 context->handleError(
1220 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1221 return false;
1222 }
1223
1224 switch (pname)
1225 {
1226 case GL_UNIFORM_BLOCK_BINDING:
1227 case GL_UNIFORM_BLOCK_DATA_SIZE:
1228 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1229 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1230 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1231 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1232 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1233 break;
1234
1235 default:
1236 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1237 return false;
1238 }
1239
1240 if (length)
1241 {
1242 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1243 {
1244 const UniformBlock &uniformBlock =
1245 programObject->getUniformBlockByIndex(uniformBlockIndex);
1246 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1247 }
1248 else
1249 {
1250 *length = 1;
1251 }
1252 }
1253
1254 return true;
1255}
1256
Geoff Langebebe1c2016-10-14 12:01:31 -04001257bool ValidateGetBufferParameterBase(ValidationContext *context,
1258 GLenum target,
1259 GLenum pname,
1260 bool pointerVersion,
1261 GLsizei *numParams)
1262{
1263 if (numParams)
1264 {
1265 *numParams = 0;
1266 }
1267
1268 if (!ValidBufferTarget(context, target))
1269 {
1270 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1271 return false;
1272 }
1273
1274 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1275 if (!buffer)
1276 {
1277 // A null buffer means that "0" is bound to the requested buffer target
1278 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1279 return false;
1280 }
1281
1282 const Extensions &extensions = context->getExtensions();
1283
1284 switch (pname)
1285 {
1286 case GL_BUFFER_USAGE:
1287 case GL_BUFFER_SIZE:
1288 break;
1289
1290 case GL_BUFFER_ACCESS_OES:
1291 if (!extensions.mapBuffer)
1292 {
1293 context->handleError(
Jamie Madillcc6ac252017-01-25 12:57:21 -08001294 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001295 return false;
1296 }
1297 break;
1298
1299 case GL_BUFFER_MAPPED:
1300 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1301 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1302 !extensions.mapBufferRange)
1303 {
1304 context->handleError(Error(
1305 GL_INVALID_ENUM,
Jamie Madillcc6ac252017-01-25 12:57:21 -08001306 "pname requires OpenGL ES 3.0, GL_OES_mapbuffer or GL_EXT_map_buffer_range."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001307 return false;
1308 }
1309 break;
1310
1311 case GL_BUFFER_MAP_POINTER:
1312 if (!pointerVersion)
1313 {
1314 context->handleError(
1315 Error(GL_INVALID_ENUM,
1316 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1317 return false;
1318 }
1319 break;
1320
1321 case GL_BUFFER_ACCESS_FLAGS:
1322 case GL_BUFFER_MAP_OFFSET:
1323 case GL_BUFFER_MAP_LENGTH:
1324 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1325 {
1326 context->handleError(Error(
1327 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1328 return false;
1329 }
1330 break;
1331
1332 default:
1333 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1334 return false;
1335 }
1336
1337 // All buffer parameter queries return one value.
1338 if (numParams)
1339 {
1340 *numParams = 1;
1341 }
1342
1343 return true;
1344}
1345
Geoff Lang0a9661f2016-10-20 10:59:20 -07001346bool ValidateGetInternalFormativBase(Context *context,
1347 GLenum target,
1348 GLenum internalformat,
1349 GLenum pname,
1350 GLsizei bufSize,
1351 GLsizei *numParams)
1352{
1353 if (numParams)
1354 {
1355 *numParams = 0;
1356 }
1357
1358 if (context->getClientMajorVersion() < 3)
1359 {
1360 context->handleError(
1361 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1362 return false;
1363 }
1364
1365 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1366 if (!formatCaps.renderable)
1367 {
1368 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1369 return false;
1370 }
1371
1372 switch (target)
1373 {
1374 case GL_RENDERBUFFER:
1375 break;
1376
JiangYizhoubddc46b2016-12-09 09:50:51 +08001377 case GL_TEXTURE_2D_MULTISAMPLE:
1378 if (context->getClientVersion() < ES_3_1)
1379 {
1380 context->handleError(
1381 Error(GL_INVALID_OPERATION, "Texture target requires at least OpenGL ES 3.1."));
1382 return false;
1383 }
1384 break;
1385
Geoff Lang0a9661f2016-10-20 10:59:20 -07001386 default:
1387 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1388 return false;
1389 }
1390
1391 if (bufSize < 0)
1392 {
1393 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1394 return false;
1395 }
1396
1397 GLsizei maxWriteParams = 0;
1398 switch (pname)
1399 {
1400 case GL_NUM_SAMPLE_COUNTS:
1401 maxWriteParams = 1;
1402 break;
1403
1404 case GL_SAMPLES:
1405 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1406 break;
1407
1408 default:
1409 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1410 return false;
1411 }
1412
1413 if (numParams)
1414 {
1415 // glGetInternalFormativ will not overflow bufSize
1416 *numParams = std::min(bufSize, maxWriteParams);
1417 }
1418
1419 return true;
1420}
1421
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001422bool ValidateUniformCommonBase(gl::Context *context,
1423 gl::Program *program,
1424 GLint location,
1425 GLsizei count,
1426 const LinkedUniform **uniformOut)
1427{
1428 // TODO(Jiajia): Add image uniform check in future.
1429 if (count < 0)
1430 {
1431 context->handleError(Error(GL_INVALID_VALUE));
1432 return false;
1433 }
1434
1435 if (!program || !program->isLinked())
1436 {
1437 context->handleError(Error(GL_INVALID_OPERATION));
1438 return false;
1439 }
1440
1441 if (location == -1)
1442 {
1443 // Silently ignore the uniform command
1444 return false;
1445 }
1446
1447 const auto &uniformLocations = program->getUniformLocations();
1448 size_t castedLocation = static_cast<size_t>(location);
1449 if (castedLocation >= uniformLocations.size())
1450 {
1451 context->handleError(Error(GL_INVALID_OPERATION, "Invalid uniform location"));
1452 return false;
1453 }
1454
1455 const auto &uniformLocation = uniformLocations[castedLocation];
1456 if (uniformLocation.ignored)
1457 {
1458 // Silently ignore the uniform command
1459 return false;
1460 }
1461
1462 if (!uniformLocation.used)
1463 {
1464 context->handleError(Error(GL_INVALID_OPERATION));
1465 return false;
1466 }
1467
1468 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
1469
1470 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
1471 if (!uniform.isArray() && count > 1)
1472 {
1473 context->handleError(Error(GL_INVALID_OPERATION));
1474 return false;
1475 }
1476
1477 *uniformOut = &uniform;
1478 return true;
1479}
1480
Frank Henigman999b0fd2017-02-02 21:45:55 -05001481bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -05001482 GLenum uniformType,
1483 GLsizei count,
1484 const GLint *value)
1485{
1486 // Value type is GL_INT, because we only get here from glUniform1i{v}.
1487 // It is compatible with INT or BOOL.
1488 // Do these cheap tests first, for a little extra speed.
1489 if (GL_INT == uniformType || GL_BOOL == uniformType)
1490 {
1491 return true;
1492 }
1493
1494 if (IsSamplerType(uniformType))
1495 {
Frank Henigman999b0fd2017-02-02 21:45:55 -05001496 // Check that the values are in range.
1497 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
1498 for (GLsizei i = 0; i < count; ++i)
1499 {
1500 if (value[i] < 0 || value[i] >= max)
1501 {
1502 context->handleError(Error(GL_INVALID_VALUE, "sampler uniform value out of range"));
1503 return false;
1504 }
1505 }
Frank Henigmana98a6472017-02-02 21:38:32 -05001506 return true;
1507 }
1508
1509 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1510 return false;
1511}
1512
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001513bool ValidateUniformValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1514{
1515 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -05001516 // Do the cheaper test first, for a little extra speed.
1517 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001518 {
1519 return true;
1520 }
1521
1522 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1523 return false;
1524}
1525
1526bool ValidateUniformMatrixValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1527{
1528 // Check that the value type is compatible with uniform type.
1529 if (valueType == uniformType)
1530 {
1531 return true;
1532 }
1533
1534 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1535 return false;
1536}
1537
Geoff Langf41a7152016-09-19 15:11:17 -04001538} // anonymous namespace
1539
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001540bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001541{
Jamie Madilld7460c72014-01-21 16:38:14 -05001542 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001543 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001544 case GL_TEXTURE_2D:
1545 case GL_TEXTURE_CUBE_MAP:
1546 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001547
He Yunchaoced53ae2016-11-29 15:00:51 +08001548 case GL_TEXTURE_3D:
1549 case GL_TEXTURE_2D_ARRAY:
1550 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001551
He Yunchaoced53ae2016-11-29 15:00:51 +08001552 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001553 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001554
He Yunchaoced53ae2016-11-29 15:00:51 +08001555 default:
1556 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001557 }
Jamie Madill35d15012013-10-07 10:46:37 -04001558}
1559
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001560bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1561{
1562 switch (target)
1563 {
1564 case GL_TEXTURE_2D:
1565 case GL_TEXTURE_CUBE_MAP:
1566 return true;
1567
1568 default:
1569 return false;
1570 }
1571}
1572
1573bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1574{
1575 switch (target)
1576 {
1577 case GL_TEXTURE_3D:
1578 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001579 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001580
1581 default:
1582 return false;
1583 }
1584}
1585
Ian Ewellbda75592016-04-18 17:25:54 -04001586// Most texture GL calls are not compatible with external textures, so we have a separate validation
1587// function for use in the GL calls that do
1588bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1589{
1590 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1591 (context->getExtensions().eglImageExternal ||
1592 context->getExtensions().eglStreamConsumerExternal);
1593}
1594
Shannon Woods4dfed832014-03-17 20:03:39 -04001595// This function differs from ValidTextureTarget in that the target must be
1596// usable as the destination of a 2D operation-- so a cube face is valid, but
1597// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001598// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001599bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001600{
1601 switch (target)
1602 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001603 case GL_TEXTURE_2D:
1604 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1605 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1606 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1607 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1608 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1609 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1610 return true;
1611 default:
1612 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001613 }
1614}
1615
1616bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1617{
1618 switch (target)
1619 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001620 case GL_TEXTURE_3D:
1621 case GL_TEXTURE_2D_ARRAY:
1622 return true;
1623 default:
1624 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001625 }
1626}
1627
He Yunchao11b038b2016-11-22 21:24:04 +08001628bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1629{
1630 switch (target)
1631 {
1632 case GL_TEXTURE_2D:
1633 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1634 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1635 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1636 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1637 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1638 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1639 case GL_TEXTURE_3D:
1640 case GL_TEXTURE_2D_ARRAY:
1641 case GL_TEXTURE_2D_MULTISAMPLE:
1642 return true;
1643 default:
1644 return false;
1645 }
1646}
1647
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001648bool ValidFramebufferTarget(GLenum target)
1649{
He Yunchaoced53ae2016-11-29 15:00:51 +08001650 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1651 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001652 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001653
1654 switch (target)
1655 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001656 case GL_FRAMEBUFFER:
1657 return true;
1658 case GL_READ_FRAMEBUFFER:
1659 return true;
1660 case GL_DRAW_FRAMEBUFFER:
1661 return true;
1662 default:
1663 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001664 }
1665}
1666
Jamie Madill29639852016-09-02 15:00:09 -04001667bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001668{
1669 switch (target)
1670 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001671 case GL_ARRAY_BUFFER:
1672 case GL_ELEMENT_ARRAY_BUFFER:
1673 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001674
He Yunchaoced53ae2016-11-29 15:00:51 +08001675 case GL_PIXEL_PACK_BUFFER:
1676 case GL_PIXEL_UNPACK_BUFFER:
1677 return (context->getExtensions().pixelBufferObject ||
1678 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001679
He Yunchaoced53ae2016-11-29 15:00:51 +08001680 case GL_COPY_READ_BUFFER:
1681 case GL_COPY_WRITE_BUFFER:
1682 case GL_TRANSFORM_FEEDBACK_BUFFER:
1683 case GL_UNIFORM_BUFFER:
1684 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001685
He Yunchaoced53ae2016-11-29 15:00:51 +08001686 case GL_ATOMIC_COUNTER_BUFFER:
1687 case GL_SHADER_STORAGE_BUFFER:
1688 case GL_DRAW_INDIRECT_BUFFER:
1689 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001690 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001691
He Yunchaoced53ae2016-11-29 15:00:51 +08001692 default:
1693 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001694 }
1695}
1696
Jamie Madillc29968b2016-01-20 11:17:23 -05001697bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001698{
Jamie Madillc29968b2016-01-20 11:17:23 -05001699 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001700 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001701 switch (target)
1702 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001703 case GL_TEXTURE_2D:
1704 maxDimension = caps.max2DTextureSize;
1705 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001706 case GL_TEXTURE_CUBE_MAP:
1707 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1708 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1709 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1710 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1711 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1712 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1713 maxDimension = caps.maxCubeMapTextureSize;
1714 break;
1715 case GL_TEXTURE_3D:
1716 maxDimension = caps.max3DTextureSize;
1717 break;
1718 case GL_TEXTURE_2D_ARRAY:
1719 maxDimension = caps.max2DTextureSize;
1720 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001721 case GL_TEXTURE_2D_MULTISAMPLE:
1722 maxDimension = caps.max2DTextureSize;
1723 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001724 default:
1725 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001726 }
1727
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001728 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001729}
1730
Geoff Langcc507aa2016-12-12 10:09:52 -05001731bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001732 GLenum target,
1733 GLint level,
1734 GLsizei width,
1735 GLsizei height,
1736 GLsizei depth,
1737 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001738{
1739 if (level < 0 || width < 0 || height < 0 || depth < 0)
1740 {
1741 return false;
1742 }
1743
Austin Kinross08528e12015-10-07 16:24:40 -07001744 // TexSubImage parameters can be NPOT without textureNPOT extension,
1745 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001746 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001747 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001748 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001749 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001750 {
1751 return false;
1752 }
1753
1754 if (!ValidMipLevel(context, target, level))
1755 {
1756 return false;
1757 }
1758
1759 return true;
1760}
1761
Geoff Lang0d8b7242015-09-09 14:56:53 -04001762bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1763{
1764 // List of compressed format that require that the texture size is smaller than or a multiple of
1765 // the compressed block size.
1766 switch (internalFormat)
1767 {
1768 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1769 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1770 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1771 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001772 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001773 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1774 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1775 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1776 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1777 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
1778 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001779 return true;
1780
1781 default:
1782 return false;
1783 }
1784}
1785
Jamie Madillc29968b2016-01-20 11:17:23 -05001786bool ValidCompressedImageSize(const ValidationContext *context,
1787 GLenum internalFormat,
Geoff Lang44ff5a72017-02-03 15:15:43 -05001788 GLint xoffset,
1789 GLint yoffset,
Jamie Madillc29968b2016-01-20 11:17:23 -05001790 GLsizei width,
1791 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001792{
Geoff Lang5d601382014-07-22 15:14:06 -04001793 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1794 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001795 {
1796 return false;
1797 }
1798
Geoff Lang44ff5a72017-02-03 15:15:43 -05001799 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001800 {
1801 return false;
1802 }
1803
Geoff Lang0d8b7242015-09-09 14:56:53 -04001804 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1805 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001806 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
1807 yoffset % formatInfo.compressedBlockHeight != 0 ||
1808 (static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
Geoff Lang0d8b7242015-09-09 14:56:53 -04001809 width % formatInfo.compressedBlockWidth != 0) ||
1810 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1811 height % formatInfo.compressedBlockHeight != 0))
1812 {
1813 return false;
1814 }
1815 }
1816
Geoff Langd4f180b2013-09-24 13:57:44 -04001817 return true;
1818}
1819
Geoff Langff5b2d52016-09-07 11:32:23 -04001820bool ValidImageDataSize(ValidationContext *context,
1821 GLenum textureTarget,
1822 GLsizei width,
1823 GLsizei height,
1824 GLsizei depth,
1825 GLenum internalFormat,
1826 GLenum type,
1827 const GLvoid *pixels,
1828 GLsizei imageSize)
1829{
1830 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1831 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1832 {
1833 // Checks are not required
1834 return true;
1835 }
1836
1837 // ...the data would be unpacked from the buffer object such that the memory reads required
1838 // would exceed the data store size.
1839 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1840 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1841 const gl::Extents size(width, height, depth);
1842 const auto &unpack = context->getGLState().getUnpackState();
1843
1844 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1845 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1846 if (endByteOrErr.isError())
1847 {
1848 context->handleError(endByteOrErr.getError());
1849 return false;
1850 }
1851
1852 GLuint endByte = endByteOrErr.getResult();
1853
1854 if (pixelUnpackBuffer)
1855 {
1856 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1857 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1858 checkedEndByte += checkedOffset;
1859
1860 if (!checkedEndByte.IsValid() ||
1861 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1862 {
1863 // Overflow past the end of the buffer
1864 context->handleError(Error(GL_INVALID_OPERATION));
1865 return false;
1866 }
1867 }
1868 else
1869 {
1870 ASSERT(imageSize >= 0);
1871 if (pixels == nullptr && imageSize != 0)
1872 {
1873 context->handleError(
1874 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001875 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001876 }
1877
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001878 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001879 {
1880 context->handleError(
1881 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1882 return false;
1883 }
1884 }
1885
1886 return true;
1887}
1888
Geoff Lang37dde692014-01-31 16:34:54 -05001889bool ValidQueryType(const Context *context, GLenum queryType)
1890{
He Yunchaoced53ae2016-11-29 15:00:51 +08001891 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1892 "GL extension enums not equal.");
1893 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1894 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001895
1896 switch (queryType)
1897 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001898 case GL_ANY_SAMPLES_PASSED:
1899 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1900 return true;
1901 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1902 return (context->getClientMajorVersion() >= 3);
1903 case GL_TIME_ELAPSED_EXT:
1904 return context->getExtensions().disjointTimerQuery;
1905 case GL_COMMANDS_COMPLETED_CHROMIUM:
1906 return context->getExtensions().syncQuery;
1907 default:
1908 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001909 }
1910}
1911
Geoff Lang2d62ab72017-03-23 16:54:40 -04001912bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1913 GLenum type,
1914 GLboolean normalized,
1915 GLsizei stride,
1916 const GLvoid *ptr,
1917 bool pureInteger)
1918{
1919 ASSERT(context->getExtensions().webglCompatibility);
1920
1921 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1922 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1923 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1924 // parameter exceeds 255.
1925 constexpr GLsizei kMaxWebGLStride = 255;
1926 if (stride > kMaxWebGLStride)
1927 {
1928 context->handleError(
1929 Error(GL_INVALID_VALUE, "Stride is over the maximum stride allowed by WebGL."));
1930 return false;
1931 }
1932
1933 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1934 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1935 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1936 // or an INVALID_OPERATION error is generated.
1937 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1938 size_t typeSize = GetVertexFormatTypeSize(internalType);
1939
1940 ASSERT(isPow2(typeSize) && typeSize > 0);
1941 size_t sizeMask = (typeSize - 1);
1942 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1943 {
1944 context->handleError(
1945 Error(GL_INVALID_OPERATION, "Offset is not a multiple of the type size."));
1946 return false;
1947 }
1948
1949 if ((stride & sizeMask) != 0)
1950 {
1951 context->handleError(
1952 Error(GL_INVALID_OPERATION, "Stride is not a multiple of the type size."));
1953 return false;
1954 }
1955
1956 return true;
1957}
1958
Jamie Madillef300b12016-10-07 15:12:09 -04001959Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001960{
He Yunchaoced53ae2016-11-29 15:00:51 +08001961 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1962 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1963 // or program object and INVALID_OPERATION if the provided name identifies an object
1964 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001965
Dian Xiang769769a2015-09-09 15:20:08 -07001966 Program *validProgram = context->getProgram(id);
1967
1968 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001969 {
Dian Xiang769769a2015-09-09 15:20:08 -07001970 if (context->getShader(id))
1971 {
Jamie Madill437fa652016-05-03 15:13:24 -04001972 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001973 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1974 }
1975 else
1976 {
Jamie Madill437fa652016-05-03 15:13:24 -04001977 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001978 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001979 }
Dian Xiang769769a2015-09-09 15:20:08 -07001980
1981 return validProgram;
1982}
1983
Jamie Madillef300b12016-10-07 15:12:09 -04001984Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001985{
1986 // See ValidProgram for spec details.
1987
1988 Shader *validShader = context->getShader(id);
1989
1990 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001991 {
Dian Xiang769769a2015-09-09 15:20:08 -07001992 if (context->getProgram(id))
1993 {
Jamie Madill437fa652016-05-03 15:13:24 -04001994 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001995 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1996 }
1997 else
1998 {
Jamie Madill437fa652016-05-03 15:13:24 -04001999 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07002000 }
Geoff Lang48dcae72014-02-05 16:28:24 -05002001 }
Dian Xiang769769a2015-09-09 15:20:08 -07002002
2003 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05002004}
2005
Geoff Langb1196682014-07-23 13:47:29 -04002006bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04002007{
2008 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
2009 {
2010 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
2011
Geoff Langaae65a42014-05-26 12:43:44 -04002012 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04002013 {
Jamie Madill437fa652016-05-03 15:13:24 -04002014 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002015 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04002016 }
2017 }
2018 else
2019 {
2020 switch (attachment)
2021 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002022 case GL_DEPTH_ATTACHMENT:
2023 case GL_STENCIL_ATTACHMENT:
2024 break;
Jamie Madillb4472272014-07-03 10:38:55 -04002025
He Yunchaoced53ae2016-11-29 15:00:51 +08002026 case GL_DEPTH_STENCIL_ATTACHMENT:
2027 if (!context->getExtensions().webglCompatibility &&
2028 context->getClientMajorVersion() < 3)
2029 {
2030 context->handleError(Error(GL_INVALID_ENUM));
2031 return false;
2032 }
2033 break;
Jamie Madillb4472272014-07-03 10:38:55 -04002034
He Yunchaoced53ae2016-11-29 15:00:51 +08002035 default:
2036 context->handleError(Error(GL_INVALID_ENUM));
2037 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04002038 }
2039 }
2040
2041 return true;
2042}
2043
Jamie Madille8fb6402017-02-14 17:56:40 -05002044bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08002045 GLenum target,
2046 GLsizei samples,
2047 GLenum internalformat,
2048 GLsizei width,
2049 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002050{
2051 switch (target)
2052 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002053 case GL_RENDERBUFFER:
2054 break;
2055 default:
2056 context->handleError(Error(GL_INVALID_ENUM));
2057 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002058 }
2059
2060 if (width < 0 || height < 0 || samples < 0)
2061 {
Jamie Madill437fa652016-05-03 15:13:24 -04002062 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002063 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002064 }
2065
Jamie Madill4e0e6f82017-02-17 11:06:03 -05002066 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
2067 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
2068
2069 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04002070 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002071 {
Jamie Madill437fa652016-05-03 15:13:24 -04002072 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002073 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002074 }
2075
2076 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
2077 // 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 -08002078 // only sized internal formats.
Jamie Madill4e0e6f82017-02-17 11:06:03 -05002079 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(convertedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04002080 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002081 {
Jamie Madill437fa652016-05-03 15:13:24 -04002082 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002083 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002084 }
2085
Geoff Langaae65a42014-05-26 12:43:44 -04002086 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002087 {
Jamie Madill437fa652016-05-03 15:13:24 -04002088 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002089 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002090 }
2091
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002092 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002093 if (handle == 0)
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;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002097 }
2098
2099 return true;
2100}
2101
He Yunchaoced53ae2016-11-29 15:00:51 +08002102bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
2103 GLenum target,
2104 GLenum attachment,
2105 GLenum renderbuffertarget,
2106 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002107{
Shannon Woods1da3cf62014-06-27 15:32:23 -04002108 if (!ValidFramebufferTarget(target))
2109 {
Jamie Madill437fa652016-05-03 15:13:24 -04002110 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002111 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04002112 }
2113
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002114 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002115
Jamie Madill84115c92015-04-23 15:00:07 -04002116 ASSERT(framebuffer);
2117 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002118 {
Jamie Madill437fa652016-05-03 15:13:24 -04002119 context->handleError(
2120 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002121 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002122 }
2123
Jamie Madillb4472272014-07-03 10:38:55 -04002124 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002125 {
Jamie Madillb4472272014-07-03 10:38:55 -04002126 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002127 }
2128
Jamie Madillab9d82c2014-01-21 16:38:14 -05002129 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2130 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2131 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2132 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2133 if (renderbuffer != 0)
2134 {
2135 if (!context->getRenderbuffer(renderbuffer))
2136 {
Jamie Madill437fa652016-05-03 15:13:24 -04002137 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002138 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05002139 }
2140 }
2141
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002142 return true;
2143}
2144
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002145bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002146 GLint srcX0,
2147 GLint srcY0,
2148 GLint srcX1,
2149 GLint srcY1,
2150 GLint dstX0,
2151 GLint dstY0,
2152 GLint dstX1,
2153 GLint dstY1,
2154 GLbitfield mask,
2155 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002156{
2157 switch (filter)
2158 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002159 case GL_NEAREST:
2160 break;
2161 case GL_LINEAR:
2162 break;
2163 default:
2164 context->handleError(Error(GL_INVALID_ENUM));
2165 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002166 }
2167
2168 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
2169 {
Jamie Madill437fa652016-05-03 15:13:24 -04002170 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002171 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002172 }
2173
2174 if (mask == 0)
2175 {
2176 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
2177 // buffers are copied.
2178 return false;
2179 }
2180
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002181 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
2182 // color buffer, leaving only nearest being unfiltered from above
2183 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
2184 {
Jamie Madill437fa652016-05-03 15:13:24 -04002185 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002186 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002187 }
2188
Jamie Madill51f40ec2016-06-15 14:06:00 -04002189 const auto &glState = context->getGLState();
2190 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2191 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05002192
2193 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002194 {
Jamie Madill437fa652016-05-03 15:13:24 -04002195 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002196 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002197 }
2198
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002199 if (readFramebuffer->id() == drawFramebuffer->id())
2200 {
2201 context->handleError(Error(GL_INVALID_OPERATION));
2202 return false;
2203 }
2204
Jamie Madill51f40ec2016-06-15 14:06:00 -04002205 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002206 {
Jamie Madill437fa652016-05-03 15:13:24 -04002207 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002208 return false;
2209 }
2210
Jamie Madill51f40ec2016-06-15 14:06:00 -04002211 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002212 {
Jamie Madill437fa652016-05-03 15:13:24 -04002213 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002214 return false;
2215 }
2216
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002217 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002218 {
Jamie Madill437fa652016-05-03 15:13:24 -04002219 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002220 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002221 }
2222
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002223 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2224
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002225 if (mask & GL_COLOR_BUFFER_BIT)
2226 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002227 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002228 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002229
He Yunchao66a41a22016-12-15 16:45:05 +08002230 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002231 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002232 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002233
Geoff Langa15472a2015-08-11 11:48:03 -04002234 for (size_t drawbufferIdx = 0;
2235 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002236 {
Geoff Langa15472a2015-08-11 11:48:03 -04002237 const FramebufferAttachment *attachment =
2238 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2239 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002240 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002241 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002242
Geoff Langb2f3d052013-08-13 12:49:27 -04002243 // The GL ES 3.0.2 spec (pg 193) states that:
2244 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002245 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2246 // as well
2247 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2248 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002249 // Changes with EXT_color_buffer_float:
2250 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002251 GLenum readComponentType = readFormat.info->componentType;
2252 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002253 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002254 readComponentType == GL_SIGNED_NORMALIZED);
2255 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2256 drawComponentType == GL_SIGNED_NORMALIZED);
2257
2258 if (extensions.colorBufferFloat)
2259 {
2260 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2261 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2262
2263 if (readFixedOrFloat != drawFixedOrFloat)
2264 {
Jamie Madill437fa652016-05-03 15:13:24 -04002265 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002266 "If the read buffer contains fixed-point or "
2267 "floating-point values, the draw buffer "
2268 "must as well."));
2269 return false;
2270 }
2271 }
2272 else if (readFixedPoint != drawFixedPoint)
2273 {
Jamie Madill437fa652016-05-03 15:13:24 -04002274 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002275 "If the read buffer contains fixed-point "
2276 "values, the draw buffer must as well."));
2277 return false;
2278 }
2279
2280 if (readComponentType == GL_UNSIGNED_INT &&
2281 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002282 {
Jamie Madill437fa652016-05-03 15:13:24 -04002283 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002284 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002285 }
2286
Jamie Madill6163c752015-12-07 16:32:59 -05002287 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002288 {
Jamie Madill437fa652016-05-03 15:13:24 -04002289 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002290 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002291 }
2292
Jamie Madilla3944d42016-07-22 22:13:26 -04002293 if (readColorBuffer->getSamples() > 0 &&
2294 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
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 }
2299 }
2300 }
2301
Jamie Madilla3944d42016-07-22 22:13:26 -04002302 if ((readFormat.info->componentType == GL_INT ||
2303 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2304 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002305 {
Jamie Madill437fa652016-05-03 15:13:24 -04002306 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002307 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002308 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002309 }
He Yunchao66a41a22016-12-15 16:45:05 +08002310 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2311 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2312 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2313 // situation is an application error that would lead to a crash in ANGLE.
2314 else if (drawFramebuffer->hasEnabledDrawBuffer())
2315 {
2316 context->handleError(Error(
2317 GL_INVALID_OPERATION,
2318 "Attempt to read from a missing color attachment of a complete framebuffer."));
2319 return false;
2320 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002321 }
2322
He Yunchaoced53ae2016-11-29 15:00:51 +08002323 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002324 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2325 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002326 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002327 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002328 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002329 const gl::FramebufferAttachment *readBuffer =
2330 readFramebuffer->getAttachment(attachments[i]);
2331 const gl::FramebufferAttachment *drawBuffer =
2332 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002333
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002334 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002335 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002336 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002337 {
Jamie Madill437fa652016-05-03 15:13:24 -04002338 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002339 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002340 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002341
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002342 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002343 {
Jamie Madill437fa652016-05-03 15:13:24 -04002344 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002345 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002346 }
2347 }
He Yunchao66a41a22016-12-15 16:45:05 +08002348 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2349 else if (drawBuffer)
2350 {
2351 context->handleError(Error(GL_INVALID_OPERATION,
2352 "Attempt to read from a missing depth/stencil "
2353 "attachment of a complete framebuffer."));
2354 return false;
2355 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002356 }
2357 }
2358
2359 return true;
2360}
2361
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002362bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002363 GLint x,
2364 GLint y,
2365 GLsizei width,
2366 GLsizei height,
2367 GLenum format,
2368 GLenum type,
2369 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002370{
Geoff Lange93daba2017-03-30 13:54:40 -04002371 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
2372 nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04002373}
2374
2375bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2376 GLint x,
2377 GLint y,
2378 GLsizei width,
2379 GLsizei height,
2380 GLenum format,
2381 GLenum type,
2382 GLsizei bufSize,
2383 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04002384 GLsizei *columns,
2385 GLsizei *rows,
Geoff Lang62fce5b2016-09-30 10:46:35 -04002386 GLvoid *pixels)
2387{
2388 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002389 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002390 return false;
2391 }
2392
Geoff Lang62fce5b2016-09-30 10:46:35 -04002393 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04002394 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002395 {
Geoff Langb1196682014-07-23 13:47:29 -04002396 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002397 }
2398
Geoff Lang62fce5b2016-09-30 10:46:35 -04002399 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002400 {
Geoff Langb1196682014-07-23 13:47:29 -04002401 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002402 }
2403
Jamie Madillc29968b2016-01-20 11:17:23 -05002404 return true;
2405}
2406
2407bool ValidateReadnPixelsEXT(Context *context,
2408 GLint x,
2409 GLint y,
2410 GLsizei width,
2411 GLsizei height,
2412 GLenum format,
2413 GLenum type,
2414 GLsizei bufSize,
2415 GLvoid *pixels)
2416{
2417 if (bufSize < 0)
2418 {
Jamie Madill437fa652016-05-03 15:13:24 -04002419 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002420 return false;
2421 }
2422
Geoff Lang62fce5b2016-09-30 10:46:35 -04002423 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04002424 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04002425}
Jamie Madill26e91952014-03-05 15:01:27 -05002426
Geoff Lang62fce5b2016-09-30 10:46:35 -04002427bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2428 GLint x,
2429 GLint y,
2430 GLsizei width,
2431 GLsizei height,
2432 GLenum format,
2433 GLenum type,
2434 GLsizei bufSize,
2435 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04002436 GLsizei *columns,
2437 GLsizei *rows,
Geoff Lang62fce5b2016-09-30 10:46:35 -04002438 GLvoid *data)
2439{
2440 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002441 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002442 return false;
2443 }
2444
Geoff Lange93daba2017-03-30 13:54:40 -04002445 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2446 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002447 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002448 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002449 }
2450
Geoff Lang62fce5b2016-09-30 10:46:35 -04002451 if (!ValidateRobustBufferSize(context, bufSize, *length))
2452 {
2453 return false;
2454 }
2455
2456 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002457}
2458
Olli Etuaho41997e72016-03-10 13:38:39 +02002459bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002460{
2461 if (!context->getExtensions().occlusionQueryBoolean &&
2462 !context->getExtensions().disjointTimerQuery)
2463 {
Jamie Madill437fa652016-05-03 15:13:24 -04002464 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002465 return false;
2466 }
2467
Olli Etuaho41997e72016-03-10 13:38:39 +02002468 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002469}
2470
Olli Etuaho41997e72016-03-10 13:38:39 +02002471bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002472{
2473 if (!context->getExtensions().occlusionQueryBoolean &&
2474 !context->getExtensions().disjointTimerQuery)
2475 {
Jamie Madill437fa652016-05-03 15:13:24 -04002476 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002477 return false;
2478 }
2479
Olli Etuaho41997e72016-03-10 13:38:39 +02002480 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002481}
2482
2483bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002484{
2485 if (!ValidQueryType(context, target))
2486 {
Jamie Madill437fa652016-05-03 15:13:24 -04002487 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002488 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002489 }
2490
2491 if (id == 0)
2492 {
Jamie Madill437fa652016-05-03 15:13:24 -04002493 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002494 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002495 }
2496
2497 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2498 // of zero, if the active query object name for <target> is non-zero (for the
2499 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2500 // the active query for either target is non-zero), if <id> is the name of an
2501 // existing query object whose type does not match <target>, or if <id> is the
2502 // active query object name for any query type, the error INVALID_OPERATION is
2503 // generated.
2504
2505 // Ensure no other queries are active
2506 // NOTE: If other queries than occlusion are supported, we will need to check
2507 // separately that:
2508 // a) The query ID passed is not the current active query for any target/type
2509 // b) There are no active queries for the requested target (and in the case
2510 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2511 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002512
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002513 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002514 {
Jamie Madill437fa652016-05-03 15:13:24 -04002515 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002516 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002517 }
2518
2519 Query *queryObject = context->getQuery(id, true, target);
2520
2521 // check that name was obtained with glGenQueries
2522 if (!queryObject)
2523 {
Jamie Madill437fa652016-05-03 15:13:24 -04002524 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002525 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002526 }
2527
2528 // check for type mismatch
2529 if (queryObject->getType() != target)
2530 {
Jamie Madill437fa652016-05-03 15:13:24 -04002531 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002532 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002533 }
2534
2535 return true;
2536}
2537
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002538bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2539{
2540 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002541 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002542 {
Jamie Madill437fa652016-05-03 15:13:24 -04002543 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002544 return false;
2545 }
2546
2547 return ValidateBeginQueryBase(context, target, id);
2548}
2549
2550bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002551{
2552 if (!ValidQueryType(context, target))
2553 {
Jamie Madill437fa652016-05-03 15:13:24 -04002554 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002555 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002556 }
2557
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002558 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002559
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002560 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002561 {
Jamie Madill437fa652016-05-03 15:13:24 -04002562 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002563 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002564 }
2565
Jamie Madill45c785d2014-05-13 14:09:34 -04002566 return true;
2567}
2568
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002569bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2570{
2571 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002572 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002573 {
Jamie Madill437fa652016-05-03 15:13:24 -04002574 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002575 return false;
2576 }
2577
2578 return ValidateEndQueryBase(context, target);
2579}
2580
2581bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2582{
2583 if (!context->getExtensions().disjointTimerQuery)
2584 {
Jamie Madill437fa652016-05-03 15:13:24 -04002585 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002586 return false;
2587 }
2588
2589 if (target != GL_TIMESTAMP_EXT)
2590 {
Jamie Madill437fa652016-05-03 15:13:24 -04002591 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002592 return false;
2593 }
2594
2595 Query *queryObject = context->getQuery(id, true, target);
2596 if (queryObject == nullptr)
2597 {
Jamie Madill437fa652016-05-03 15:13:24 -04002598 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002599 return false;
2600 }
2601
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002602 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002603 {
Jamie Madill437fa652016-05-03 15:13:24 -04002604 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002605 return false;
2606 }
2607
2608 return true;
2609}
2610
Geoff Lang2186c382016-10-14 10:54:54 -04002611bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002612{
Geoff Lang2186c382016-10-14 10:54:54 -04002613 if (numParams)
2614 {
2615 *numParams = 0;
2616 }
2617
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002618 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2619 {
Jamie Madill437fa652016-05-03 15:13:24 -04002620 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002621 return false;
2622 }
2623
2624 switch (pname)
2625 {
2626 case GL_CURRENT_QUERY_EXT:
2627 if (target == GL_TIMESTAMP_EXT)
2628 {
Jamie Madill437fa652016-05-03 15:13:24 -04002629 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002630 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2631 return false;
2632 }
2633 break;
2634 case GL_QUERY_COUNTER_BITS_EXT:
2635 if (!context->getExtensions().disjointTimerQuery ||
2636 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2637 {
Jamie Madill437fa652016-05-03 15:13:24 -04002638 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002639 return false;
2640 }
2641 break;
2642 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002643 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002644 return false;
2645 }
2646
Geoff Lang2186c382016-10-14 10:54:54 -04002647 if (numParams)
2648 {
2649 // All queries return only one value
2650 *numParams = 1;
2651 }
2652
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002653 return true;
2654}
2655
2656bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2657{
2658 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002659 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002660 {
Jamie Madill437fa652016-05-03 15:13:24 -04002661 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002662 return false;
2663 }
2664
Geoff Lang2186c382016-10-14 10:54:54 -04002665 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002666}
2667
Geoff Lang2186c382016-10-14 10:54:54 -04002668bool ValidateGetQueryivRobustANGLE(Context *context,
2669 GLenum target,
2670 GLenum pname,
2671 GLsizei bufSize,
2672 GLsizei *length,
2673 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002674{
Geoff Lang2186c382016-10-14 10:54:54 -04002675 if (!ValidateRobustEntryPoint(context, bufSize))
2676 {
2677 return false;
2678 }
2679
2680 if (!ValidateGetQueryivBase(context, target, pname, length))
2681 {
2682 return false;
2683 }
2684
2685 if (!ValidateRobustBufferSize(context, bufSize, *length))
2686 {
2687 return false;
2688 }
2689
2690 return true;
2691}
2692
2693bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2694{
2695 if (numParams)
2696 {
2697 *numParams = 0;
2698 }
2699
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002700 Query *queryObject = context->getQuery(id, false, GL_NONE);
2701
2702 if (!queryObject)
2703 {
Jamie Madill437fa652016-05-03 15:13:24 -04002704 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002705 return false;
2706 }
2707
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002708 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002709 {
Jamie Madill437fa652016-05-03 15:13:24 -04002710 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002711 return false;
2712 }
2713
2714 switch (pname)
2715 {
2716 case GL_QUERY_RESULT_EXT:
2717 case GL_QUERY_RESULT_AVAILABLE_EXT:
2718 break;
2719
2720 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002721 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002722 return false;
2723 }
2724
Geoff Lang2186c382016-10-14 10:54:54 -04002725 if (numParams)
2726 {
2727 *numParams = 1;
2728 }
2729
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002730 return true;
2731}
2732
2733bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2734{
2735 if (!context->getExtensions().disjointTimerQuery)
2736 {
Jamie Madill437fa652016-05-03 15:13:24 -04002737 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002738 return false;
2739 }
Geoff Lang2186c382016-10-14 10:54:54 -04002740 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2741}
2742
2743bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2744 GLuint id,
2745 GLenum pname,
2746 GLsizei bufSize,
2747 GLsizei *length,
2748 GLint *params)
2749{
2750 if (!context->getExtensions().disjointTimerQuery)
2751 {
2752 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2753 return false;
2754 }
2755
2756 if (!ValidateRobustEntryPoint(context, bufSize))
2757 {
2758 return false;
2759 }
2760
2761 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2762 {
2763 return false;
2764 }
2765
2766 if (!ValidateRobustBufferSize(context, bufSize, *length))
2767 {
2768 return false;
2769 }
2770
2771 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002772}
2773
2774bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2775{
2776 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002777 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002778 {
Jamie Madill437fa652016-05-03 15:13:24 -04002779 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002780 return false;
2781 }
Geoff Lang2186c382016-10-14 10:54:54 -04002782 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2783}
2784
2785bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2786 GLuint id,
2787 GLenum pname,
2788 GLsizei bufSize,
2789 GLsizei *length,
2790 GLuint *params)
2791{
2792 if (!context->getExtensions().disjointTimerQuery &&
2793 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2794 {
2795 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2796 return false;
2797 }
2798
2799 if (!ValidateRobustEntryPoint(context, bufSize))
2800 {
2801 return false;
2802 }
2803
2804 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2805 {
2806 return false;
2807 }
2808
2809 if (!ValidateRobustBufferSize(context, bufSize, *length))
2810 {
2811 return false;
2812 }
2813
2814 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002815}
2816
2817bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2818{
2819 if (!context->getExtensions().disjointTimerQuery)
2820 {
Jamie Madill437fa652016-05-03 15:13:24 -04002821 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002822 return false;
2823 }
Geoff Lang2186c382016-10-14 10:54:54 -04002824 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2825}
2826
2827bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2828 GLuint id,
2829 GLenum pname,
2830 GLsizei bufSize,
2831 GLsizei *length,
2832 GLint64 *params)
2833{
2834 if (!context->getExtensions().disjointTimerQuery)
2835 {
2836 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2837 return false;
2838 }
2839
2840 if (!ValidateRobustEntryPoint(context, bufSize))
2841 {
2842 return false;
2843 }
2844
2845 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2846 {
2847 return false;
2848 }
2849
2850 if (!ValidateRobustBufferSize(context, bufSize, *length))
2851 {
2852 return false;
2853 }
2854
2855 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002856}
2857
2858bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2859{
2860 if (!context->getExtensions().disjointTimerQuery)
2861 {
Jamie Madill437fa652016-05-03 15:13:24 -04002862 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002863 return false;
2864 }
Geoff Lang2186c382016-10-14 10:54:54 -04002865 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2866}
2867
2868bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2869 GLuint id,
2870 GLenum pname,
2871 GLsizei bufSize,
2872 GLsizei *length,
2873 GLuint64 *params)
2874{
2875 if (!context->getExtensions().disjointTimerQuery)
2876 {
2877 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2878 return false;
2879 }
2880
2881 if (!ValidateRobustEntryPoint(context, bufSize))
2882 {
2883 return false;
2884 }
2885
2886 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2887 {
2888 return false;
2889 }
2890
2891 if (!ValidateRobustBufferSize(context, bufSize, *length))
2892 {
2893 return false;
2894 }
2895
2896 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002897}
2898
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002899bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002900 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002901 GLuint program,
2902 GLint location,
2903 GLsizei count)
2904{
2905 // Check for ES31 program uniform entry points
2906 if (context->getClientVersion() < Version(3, 1))
2907 {
2908 context->handleError(Error(GL_INVALID_OPERATION));
2909 return false;
2910 }
2911
2912 const LinkedUniform *uniform = nullptr;
2913 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002914 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2915 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002916}
2917
Frank Henigmana98a6472017-02-02 21:38:32 -05002918bool ValidateProgramUniform1iv(gl::Context *context,
2919 GLuint program,
2920 GLint location,
2921 GLsizei count,
2922 const GLint *value)
2923{
2924 // Check for ES31 program uniform entry points
2925 if (context->getClientVersion() < Version(3, 1))
2926 {
2927 context->handleError(Error(GL_INVALID_OPERATION));
2928 return false;
2929 }
2930
2931 const LinkedUniform *uniform = nullptr;
2932 gl::Program *programObject = GetValidProgram(context, program);
2933 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2934 ValidateUniform1ivValue(context, uniform->type, count, value);
2935}
2936
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002937bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002938 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002939 GLuint program,
2940 GLint location,
2941 GLsizei count,
2942 GLboolean transpose)
2943{
2944 // Check for ES31 program uniform entry points
2945 if (context->getClientVersion() < Version(3, 1))
2946 {
2947 context->handleError(Error(GL_INVALID_OPERATION));
2948 return false;
2949 }
2950
2951 const LinkedUniform *uniform = nullptr;
2952 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002953 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2954 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002955}
2956
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002957bool ValidateUniform(gl::Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002958{
2959 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002960 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002961 {
Jamie Madill437fa652016-05-03 15:13:24 -04002962 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002963 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002964 }
2965
Jamie Madill62d31cb2015-09-11 13:25:51 -04002966 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002967 gl::Program *programObject = context->getGLState().getProgram();
2968 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2969 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002970}
2971
Frank Henigmana98a6472017-02-02 21:38:32 -05002972bool ValidateUniform1iv(gl::Context *context, GLint location, GLsizei count, const GLint *value)
2973{
2974 const LinkedUniform *uniform = nullptr;
2975 gl::Program *programObject = context->getGLState().getProgram();
2976 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2977 ValidateUniform1ivValue(context, uniform->type, count, value);
2978}
2979
He Yunchaoced53ae2016-11-29 15:00:51 +08002980bool ValidateUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002981 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002982 GLint location,
2983 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002984 GLboolean transpose)
2985{
2986 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002987 int rows = VariableRowCount(valueType);
2988 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002989 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002990 {
Jamie Madill437fa652016-05-03 15:13:24 -04002991 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002992 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002993 }
2994
Martin Radev1be913c2016-07-11 17:59:16 +03002995 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002996 {
Jamie Madill437fa652016-05-03 15:13:24 -04002997 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002998 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002999 }
3000
Jamie Madill62d31cb2015-09-11 13:25:51 -04003001 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003002 gl::Program *programObject = context->getGLState().getProgram();
3003 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3004 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04003005}
3006
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003007bool ValidateStateQuery(ValidationContext *context,
3008 GLenum pname,
3009 GLenum *nativeType,
3010 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04003011{
3012 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
3013 {
Jamie Madill437fa652016-05-03 15:13:24 -04003014 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003015 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003016 }
3017
Jamie Madill0af26e12015-03-05 19:54:33 -05003018 const Caps &caps = context->getCaps();
3019
Jamie Madill893ab082014-05-16 16:56:10 -04003020 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
3021 {
3022 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
3023
Jamie Madill0af26e12015-03-05 19:54:33 -05003024 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04003025 {
Jamie Madill437fa652016-05-03 15:13:24 -04003026 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003027 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003028 }
3029 }
3030
3031 switch (pname)
3032 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003033 case GL_TEXTURE_BINDING_2D:
3034 case GL_TEXTURE_BINDING_CUBE_MAP:
3035 case GL_TEXTURE_BINDING_3D:
3036 case GL_TEXTURE_BINDING_2D_ARRAY:
3037 break;
3038 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3039 if (!context->getExtensions().eglStreamConsumerExternal &&
3040 !context->getExtensions().eglImageExternal)
3041 {
3042 context->handleError(Error(GL_INVALID_ENUM,
3043 "Neither NV_EGL_stream_consumer_external nor "
3044 "GL_OES_EGL_image_external extensions enabled"));
3045 return false;
3046 }
3047 break;
Jamie Madill893ab082014-05-16 16:56:10 -04003048
He Yunchaoced53ae2016-11-29 15:00:51 +08003049 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3050 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04003051 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04003052 if (context->getGLState().getReadFramebuffer()->checkStatus(
3053 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04003054 {
Jamie Madill437fa652016-05-03 15:13:24 -04003055 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003056 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003057 }
3058
Jamie Madill51f40ec2016-06-15 14:06:00 -04003059 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
3060 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03003061
3062 if (framebuffer->getReadBufferState() == GL_NONE)
3063 {
3064 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3065 return false;
3066 }
3067
Jamie Madillb6bda4a2015-04-20 12:53:26 -04003068 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04003069 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04003070 {
Jamie Madill437fa652016-05-03 15:13:24 -04003071 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003072 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003073 }
3074 }
3075 break;
3076
He Yunchaoced53ae2016-11-29 15:00:51 +08003077 default:
3078 break;
Jamie Madill893ab082014-05-16 16:56:10 -04003079 }
3080
3081 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04003082 if (*numParams == 0)
3083 {
3084 return false;
3085 }
3086
3087 return true;
3088}
3089
3090bool ValidateRobustStateQuery(ValidationContext *context,
3091 GLenum pname,
3092 GLsizei bufSize,
3093 GLenum *nativeType,
3094 unsigned int *numParams)
3095{
3096 if (!ValidateRobustEntryPoint(context, bufSize))
3097 {
3098 return false;
3099 }
3100
3101 if (!ValidateStateQuery(context, pname, nativeType, numParams))
3102 {
3103 return false;
3104 }
3105
3106 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04003107 {
3108 return false;
3109 }
3110
3111 return true;
3112}
3113
Jamie Madillc29968b2016-01-20 11:17:23 -05003114bool ValidateCopyTexImageParametersBase(ValidationContext *context,
3115 GLenum target,
3116 GLint level,
3117 GLenum internalformat,
3118 bool isSubImage,
3119 GLint xoffset,
3120 GLint yoffset,
3121 GLint zoffset,
3122 GLint x,
3123 GLint y,
3124 GLsizei width,
3125 GLsizei height,
3126 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04003127 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04003128{
Jamie Madill560a8d82014-05-21 13:06:20 -04003129 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
3130 {
Jamie Madill437fa652016-05-03 15:13:24 -04003131 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003132 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003133 }
3134
He Yunchaoced53ae2016-11-29 15:00:51 +08003135 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3136 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04003137 {
Jamie Madill437fa652016-05-03 15:13:24 -04003138 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003139 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003140 }
3141
3142 if (border != 0)
3143 {
Jamie Madill437fa652016-05-03 15:13:24 -04003144 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003145 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003146 }
3147
3148 if (!ValidMipLevel(context, target, level))
3149 {
Jamie Madill437fa652016-05-03 15:13:24 -04003150 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003151 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003152 }
3153
Jamie Madill51f40ec2016-06-15 14:06:00 -04003154 const auto &state = context->getGLState();
3155 auto readFramebuffer = state.getReadFramebuffer();
3156 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003157 {
Jamie Madill437fa652016-05-03 15:13:24 -04003158 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003159 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003160 }
3161
Jamie Madill51f40ec2016-06-15 14:06:00 -04003162 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003163 {
Jamie Madill437fa652016-05-03 15:13:24 -04003164 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003165 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003166 }
3167
Martin Radev138064f2016-07-15 12:03:41 +03003168 if (readFramebuffer->getReadBufferState() == GL_NONE)
3169 {
3170 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3171 return false;
3172 }
3173
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003174 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3175 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003176 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003177 // situation is an application error that would lead to a crash in ANGLE.
3178 if (readFramebuffer->getReadColorbuffer() == nullptr)
3179 {
3180 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3181 return false;
3182 }
3183
Geoff Langaae65a42014-05-26 12:43:44 -04003184 const gl::Caps &caps = context->getCaps();
3185
Geoff Langaae65a42014-05-26 12:43:44 -04003186 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003187 switch (target)
3188 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003189 case GL_TEXTURE_2D:
3190 maxDimension = caps.max2DTextureSize;
3191 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003192
He Yunchaoced53ae2016-11-29 15:00:51 +08003193 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3194 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3195 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3196 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3197 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3198 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3199 maxDimension = caps.maxCubeMapTextureSize;
3200 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003201
He Yunchaoced53ae2016-11-29 15:00:51 +08003202 case GL_TEXTURE_2D_ARRAY:
3203 maxDimension = caps.max2DTextureSize;
3204 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003205
He Yunchaoced53ae2016-11-29 15:00:51 +08003206 case GL_TEXTURE_3D:
3207 maxDimension = caps.max3DTextureSize;
3208 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003209
He Yunchaoced53ae2016-11-29 15:00:51 +08003210 default:
3211 context->handleError(Error(GL_INVALID_ENUM));
3212 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003213 }
3214
Jamie Madillc29968b2016-01-20 11:17:23 -05003215 gl::Texture *texture =
3216 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003217 if (!texture)
3218 {
Jamie Madill437fa652016-05-03 15:13:24 -04003219 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003220 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003221 }
3222
Geoff Lang69cce582015-09-17 13:20:36 -04003223 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003224 {
Jamie Madill437fa652016-05-03 15:13:24 -04003225 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003226 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003227 }
3228
Geoff Lang5d601382014-07-22 15:14:06 -04003229 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3230
3231 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003232 {
Jamie Madill437fa652016-05-03 15:13:24 -04003233 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003234 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003235 }
3236
Geoff Lang44ff5a72017-02-03 15:15:43 -05003237 if (formatInfo.compressed &&
3238 !ValidCompressedImageSize(context, internalformat, xoffset, yoffset, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003239 {
Jamie Madill437fa652016-05-03 15:13:24 -04003240 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003241 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003242 }
3243
3244 if (isSubImage)
3245 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003246 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3247 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3248 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003249 {
Jamie Madill437fa652016-05-03 15:13:24 -04003250 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003251 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003252 }
3253 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003254 else
3255 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003256 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003257 {
Jamie Madill437fa652016-05-03 15:13:24 -04003258 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003259 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003260 }
3261
Geoff Langeb66a6e2016-10-31 13:06:12 -04003262 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003263 {
Jamie Madill437fa652016-05-03 15:13:24 -04003264 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003265 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003266 }
3267
3268 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003269 if (static_cast<int>(width) > maxLevelDimension ||
3270 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003271 {
Jamie Madill437fa652016-05-03 15:13:24 -04003272 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003273 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003274 }
3275 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003276
Jamie Madill0c8abca2016-07-22 20:21:26 -04003277 if (textureFormatOut)
3278 {
3279 *textureFormatOut = texture->getFormat(target, level);
3280 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003281
3282 // Detect texture copying feedback loops for WebGL.
3283 if (context->getExtensions().webglCompatibility)
3284 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05003285 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05003286 {
3287 context->handleError(Error(GL_INVALID_OPERATION,
3288 "Texture copying feedback loop formed between Framebuffer "
3289 "and specified Texture level."));
3290 return false;
3291 }
3292 }
3293
Jamie Madill560a8d82014-05-21 13:06:20 -04003294 return true;
3295}
3296
Jiajia Qind9671222016-11-29 16:30:31 +08003297bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003298{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003299 switch (mode)
3300 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003301 case GL_POINTS:
3302 case GL_LINES:
3303 case GL_LINE_LOOP:
3304 case GL_LINE_STRIP:
3305 case GL_TRIANGLES:
3306 case GL_TRIANGLE_STRIP:
3307 case GL_TRIANGLE_FAN:
3308 break;
3309 default:
3310 context->handleError(Error(GL_INVALID_ENUM));
3311 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003312 }
3313
Jamie Madill250d33f2014-06-06 17:09:03 -04003314 if (count < 0)
3315 {
Jamie Madill437fa652016-05-03 15:13:24 -04003316 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003317 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003318 }
3319
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003320 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003321
Jamie Madill250d33f2014-06-06 17:09:03 -04003322 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003323 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003324 {
Jamie Madill437fa652016-05-03 15:13:24 -04003325 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003326 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003327 }
3328
Jamie Madillcbcde722017-01-06 14:50:00 -05003329 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3330 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003331 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003332 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3333 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003334 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003335 const FramebufferAttachment *dsAttachment =
3336 framebuffer->getStencilOrDepthStencilAttachment();
3337 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003338 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003339 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003340
3341 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3342 bool differentWritemasks =
3343 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3344 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3345 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3346 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3347
3348 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003349 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003350 if (!context->getExtensions().webglCompatibility)
3351 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003352 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3353 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003354 }
Jamie Madill437fa652016-05-03 15:13:24 -04003355 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003356 return false;
3357 }
Jamie Madillac528012014-06-20 13:21:23 -04003358 }
3359
Jamie Madill51f40ec2016-06-15 14:06:00 -04003360 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003361 {
Jamie Madill437fa652016-05-03 15:13:24 -04003362 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003363 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003364 }
3365
Geoff Lang7dd2e102014-11-10 15:19:26 -05003366 gl::Program *program = state.getProgram();
3367 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003368 {
Jamie Madill437fa652016-05-03 15:13:24 -04003369 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003370 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003371 }
3372
Geoff Lang7dd2e102014-11-10 15:19:26 -05003373 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003374 {
Jamie Madill437fa652016-05-03 15:13:24 -04003375 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003376 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003377 }
3378
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003379 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003380 for (unsigned int uniformBlockIndex = 0;
3381 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003382 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003383 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003384 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003385 const OffsetBindingPointer<Buffer> &uniformBuffer =
3386 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003387
Geoff Lang5d124a62015-09-15 13:03:27 -04003388 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003389 {
3390 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003391 context->handleError(
3392 Error(GL_INVALID_OPERATION,
3393 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003394 return false;
3395 }
3396
Geoff Lang5d124a62015-09-15 13:03:27 -04003397 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003398 if (uniformBufferSize == 0)
3399 {
3400 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003401 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003402 }
3403
Jamie Madill62d31cb2015-09-11 13:25:51 -04003404 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003405 {
3406 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003407 context->handleError(
3408 Error(GL_INVALID_OPERATION,
3409 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003410 return false;
3411 }
3412 }
3413
Jamie Madilla4595b82017-01-11 17:36:34 -05003414 // Detect rendering feedback loops for WebGL.
3415 if (context->getExtensions().webglCompatibility)
3416 {
3417 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3418 {
3419 context->handleError(
3420 Error(GL_INVALID_OPERATION,
3421 "Rendering feedback loop formed between Framebuffer and active Texture."));
3422 return false;
3423 }
3424 }
3425
Jamie Madill250d33f2014-06-06 17:09:03 -04003426 // No-op if zero count
3427 return (count > 0);
3428}
3429
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003430bool ValidateDrawArrays(ValidationContext *context,
3431 GLenum mode,
3432 GLint first,
3433 GLsizei count,
3434 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003435{
Jamie Madillfd716582014-06-06 17:09:04 -04003436 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003437 {
Jamie Madill437fa652016-05-03 15:13:24 -04003438 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003439 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003440 }
3441
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003442 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003443 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003444 if (curTransformFeedback && curTransformFeedback->isActive() &&
3445 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003446 {
3447 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003448 // that does not match the current transform feedback object's draw mode (if transform
3449 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003450 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003451 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003452 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003453 }
3454
Jiajia Qind9671222016-11-29 16:30:31 +08003455 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003456 {
3457 return false;
3458 }
3459
Corentin Wallez71168a02016-12-19 15:11:18 -08003460 // Check the computation of maxVertex doesn't overflow.
3461 // - first < 0 or count < 0 have been checked as an error condition
3462 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3463 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3464 ASSERT(count > 0 && first >= 0);
3465 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3466 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003467 {
3468 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3469 return false;
3470 }
3471
Corentin Wallez71168a02016-12-19 15:11:18 -08003472 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003473 {
3474 return false;
3475 }
3476
3477 return true;
3478}
3479
He Yunchaoced53ae2016-11-29 15:00:51 +08003480bool ValidateDrawArraysInstanced(Context *context,
3481 GLenum mode,
3482 GLint first,
3483 GLsizei count,
3484 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003485{
3486 if (primcount < 0)
3487 {
Jamie Madill437fa652016-05-03 15:13:24 -04003488 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003489 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003490 }
3491
Jamie Madill2b976812014-08-25 15:47:49 -04003492 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003493 {
3494 return false;
3495 }
3496
3497 // No-op if zero primitive count
3498 return (primcount > 0);
3499}
3500
Geoff Lang87a93302014-09-16 13:29:43 -04003501static bool ValidateDrawInstancedANGLE(Context *context)
3502{
3503 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003504 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003505
Geoff Lang7dd2e102014-11-10 15:19:26 -05003506 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003507
Jiawei-Shao2597fb62016-12-09 16:38:02 +08003508 const auto &attribs = state.getVertexArray()->getVertexAttributes();
3509 const auto &bindings = state.getVertexArray()->getVertexBindings();
Jamie Madill63805b42015-08-25 13:17:39 -04003510 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003511 {
Jiawei-Shao2597fb62016-12-09 16:38:02 +08003512 const VertexAttribute &attrib = attribs[attributeIndex];
3513 const VertexBinding &binding = bindings[attrib.bindingIndex];
3514 if (program->isAttribLocationActive(attributeIndex) && binding.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003515 {
3516 return true;
3517 }
3518 }
3519
Jamie Madill437fa652016-05-03 15:13:24 -04003520 context->handleError(Error(GL_INVALID_OPERATION,
3521 "ANGLE_instanced_arrays requires that at least one active attribute"
3522 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003523 return false;
3524}
3525
He Yunchaoced53ae2016-11-29 15:00:51 +08003526bool ValidateDrawArraysInstancedANGLE(Context *context,
3527 GLenum mode,
3528 GLint first,
3529 GLsizei count,
3530 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003531{
3532 if (!ValidateDrawInstancedANGLE(context))
3533 {
3534 return false;
3535 }
3536
3537 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3538}
3539
Jiajia Qind9671222016-11-29 16:30:31 +08003540bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003541{
Jamie Madill250d33f2014-06-06 17:09:03 -04003542 switch (type)
3543 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003544 case GL_UNSIGNED_BYTE:
3545 case GL_UNSIGNED_SHORT:
3546 break;
3547 case GL_UNSIGNED_INT:
3548 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3549 {
3550 context->handleError(Error(GL_INVALID_ENUM));
3551 return false;
3552 }
3553 break;
3554 default:
3555 context->handleError(Error(GL_INVALID_ENUM));
3556 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003557 }
3558
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003559 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003560
3561 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003562 if (curTransformFeedback && curTransformFeedback->isActive() &&
3563 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003564 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003565 // It is an invalid operation to call DrawElements, DrawRangeElements or
3566 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003567 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003568 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003569 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003570 }
3571
Jiajia Qind9671222016-11-29 16:30:31 +08003572 return true;
3573}
3574
3575bool ValidateDrawElements(ValidationContext *context,
3576 GLenum mode,
3577 GLsizei count,
3578 GLenum type,
3579 const GLvoid *indices,
3580 GLsizei primcount,
3581 IndexRange *indexRangeOut)
3582{
3583 if (!ValidateDrawElementsBase(context, type))
3584 return false;
3585
3586 const State &state = context->getGLState();
3587
Jamie Madill250d33f2014-06-06 17:09:03 -04003588 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003589 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003590 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003591 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04003592 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003593 }
3594
He Yunchaoced53ae2016-11-29 15:00:51 +08003595 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003596 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003597
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003598 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3599
3600 if (context->getExtensions().webglCompatibility)
3601 {
3602 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3603 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3604 {
3605 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3606 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3607 // data type passed to the call, or an INVALID_OPERATION error is generated.
3608 context->handleError(Error(GL_INVALID_OPERATION,
3609 "indices must be a multiple of the element type size."));
3610 return false;
3611 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003612
3613 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3614 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3615 // error is generated.
3616 if (reinterpret_cast<intptr_t>(indices) < 0)
3617 {
3618 context->handleError(Error(GL_INVALID_VALUE, "Offset < 0."));
3619 return false;
3620 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003621 }
3622
3623 if (context->getExtensions().webglCompatibility ||
3624 !context->getGLState().areClientArraysEnabled())
3625 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003626 if (!elementArrayBuffer && count > 0)
3627 {
3628 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3629 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3630 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3631 context->handleError(Error(GL_INVALID_OPERATION,
3632 "There is no element array buffer bound and count > 0."));
3633 return false;
3634 }
3635 }
3636
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003637 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003638 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003639 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003640 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003641 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3642 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3643 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3644 constexpr uint64_t kMaxTypeSize = 8;
3645 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3646 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3647 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003648
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003649 uint64_t typeSize = typeBytes;
3650 uint64_t elementCount = static_cast<uint64_t>(count);
3651 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3652
3653 // Doing the multiplication here is overflow-safe
3654 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3655
3656 // The offset can be any value, check for overflows
3657 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3658 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003659 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003660 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003661 return false;
3662 }
3663
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003664 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3665 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003666 {
3667 context->handleError(
3668 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
3669 return false;
3670 }
3671 }
3672 else if (!indices)
3673 {
3674 // This is an application error that would normally result in a crash,
3675 // but we catch it and return an error
3676 context->handleError(
3677 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003678 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003679 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003680 }
3681
Jiajia Qind9671222016-11-29 16:30:31 +08003682 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003683 {
3684 return false;
3685 }
3686
Jamie Madill2b976812014-08-25 15:47:49 -04003687 // Use max index to validate if our vertex buffers are large enough for the pull.
3688 // TODO: offer fast path, with disabled index validation.
3689 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3690 if (elementArrayBuffer)
3691 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003692 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003693 Error error =
3694 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3695 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003696 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003697 {
Jamie Madill437fa652016-05-03 15:13:24 -04003698 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003699 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003700 }
3701 }
3702 else
3703 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003704 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003705 }
3706
Jamie Madille79b1e12015-11-04 16:36:37 -05003707 // If we use an index greater than our maximum supported index range, return an error.
3708 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3709 // return an error if possible here.
3710 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3711 {
Jamie Madill437fa652016-05-03 15:13:24 -04003712 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003713 return false;
3714 }
3715
Corentin Wallez92db6942016-12-09 13:10:36 -05003716 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3717 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003718 {
3719 return false;
3720 }
3721
Geoff Lang3edfe032015-09-04 16:38:24 -04003722 // No op if there are no real indices in the index data (all are primitive restart).
3723 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003724}
3725
Geoff Langb1196682014-07-23 13:47:29 -04003726bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003727 GLenum mode,
3728 GLsizei count,
3729 GLenum type,
3730 const GLvoid *indices,
3731 GLsizei primcount,
3732 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003733{
3734 if (primcount < 0)
3735 {
Jamie Madill437fa652016-05-03 15:13:24 -04003736 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003737 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003738 }
3739
Jamie Madill2b976812014-08-25 15:47:49 -04003740 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003741 {
3742 return false;
3743 }
3744
3745 // No-op zero primitive count
3746 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003747}
3748
Geoff Lang3edfe032015-09-04 16:38:24 -04003749bool ValidateDrawElementsInstancedANGLE(Context *context,
3750 GLenum mode,
3751 GLsizei count,
3752 GLenum type,
3753 const GLvoid *indices,
3754 GLsizei primcount,
3755 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003756{
3757 if (!ValidateDrawInstancedANGLE(context))
3758 {
3759 return false;
3760 }
3761
He Yunchaoced53ae2016-11-29 15:00:51 +08003762 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3763 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003764}
3765
He Yunchaoced53ae2016-11-29 15:00:51 +08003766bool ValidateFramebufferTextureBase(Context *context,
3767 GLenum target,
3768 GLenum attachment,
3769 GLuint texture,
3770 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003771{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003772 if (!ValidFramebufferTarget(target))
3773 {
Jamie Madill437fa652016-05-03 15:13:24 -04003774 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003775 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003776 }
3777
3778 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003779 {
3780 return false;
3781 }
3782
Jamie Madill55ec3b12014-07-03 10:38:57 -04003783 if (texture != 0)
3784 {
3785 gl::Texture *tex = context->getTexture(texture);
3786
3787 if (tex == NULL)
3788 {
Jamie Madill437fa652016-05-03 15:13:24 -04003789 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003790 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003791 }
3792
3793 if (level < 0)
3794 {
Jamie Madill437fa652016-05-03 15:13:24 -04003795 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003796 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003797 }
3798 }
3799
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003800 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003801 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003802
Jamie Madill84115c92015-04-23 15:00:07 -04003803 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003804 {
Jamie Madill437fa652016-05-03 15:13:24 -04003805 context->handleError(
3806 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003807 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003808 }
3809
3810 return true;
3811}
3812
He Yunchaoced53ae2016-11-29 15:00:51 +08003813bool ValidateFramebufferTexture2D(Context *context,
3814 GLenum target,
3815 GLenum attachment,
3816 GLenum textarget,
3817 GLuint texture,
3818 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003819{
He Yunchaoced53ae2016-11-29 15:00:51 +08003820 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3821 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003822 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3823 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003824 {
Jamie Madill437fa652016-05-03 15:13:24 -04003825 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003826 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003827 }
3828
3829 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003830 {
3831 return false;
3832 }
3833
Jamie Madill55ec3b12014-07-03 10:38:57 -04003834 if (texture != 0)
3835 {
3836 gl::Texture *tex = context->getTexture(texture);
3837 ASSERT(tex);
3838
Jamie Madill2a6564e2014-07-11 09:53:19 -04003839 const gl::Caps &caps = context->getCaps();
3840
Jamie Madill55ec3b12014-07-03 10:38:57 -04003841 switch (textarget)
3842 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003843 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003844 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003845 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003846 {
Jamie Madill437fa652016-05-03 15:13:24 -04003847 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003848 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003849 }
3850 if (tex->getTarget() != GL_TEXTURE_2D)
3851 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003852 context->handleError(Error(GL_INVALID_OPERATION,
3853 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003854 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003855 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003856 }
3857 break;
3858
He Yunchaoced53ae2016-11-29 15:00:51 +08003859 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3860 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3861 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3862 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3863 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3864 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003865 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003866 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003867 {
Jamie Madill437fa652016-05-03 15:13:24 -04003868 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003869 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003870 }
3871 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3872 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003873 context->handleError(Error(GL_INVALID_OPERATION,
3874 "Textarget must match the texture target type."));
3875 return false;
3876 }
3877 }
3878 break;
3879
3880 case GL_TEXTURE_2D_MULTISAMPLE:
3881 {
3882 if (context->getClientVersion() < ES_3_1)
3883 {
3884 context->handleError(Error(GL_INVALID_OPERATION,
3885 "Texture target requires at least OpenGL ES 3.1."));
3886 return false;
3887 }
3888
3889 if (level != 0)
3890 {
3891 context->handleError(
3892 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
3893 return false;
3894 }
3895 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
3896 {
3897 context->handleError(Error(GL_INVALID_OPERATION,
3898 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003899 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003900 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003901 }
3902 break;
3903
He Yunchaoced53ae2016-11-29 15:00:51 +08003904 default:
3905 context->handleError(Error(GL_INVALID_ENUM));
3906 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003907 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003908
Jamie Madilla3944d42016-07-22 22:13:26 -04003909 const Format &format = tex->getFormat(textarget, level);
3910 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003911 {
Jamie Madill437fa652016-05-03 15:13:24 -04003912 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003913 return false;
3914 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003915 }
3916
Jamie Madill570f7c82014-07-03 10:38:54 -04003917 return true;
3918}
3919
Geoff Langb1196682014-07-23 13:47:29 -04003920bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003921{
3922 if (program == 0)
3923 {
Jamie Madill437fa652016-05-03 15:13:24 -04003924 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003925 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003926 }
3927
Dian Xiang769769a2015-09-09 15:20:08 -07003928 gl::Program *programObject = GetValidProgram(context, program);
3929 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003930 {
3931 return false;
3932 }
3933
Jamie Madill0063c512014-08-25 15:47:53 -04003934 if (!programObject || !programObject->isLinked())
3935 {
Jamie Madill437fa652016-05-03 15:13:24 -04003936 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003937 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003938 }
3939
Geoff Lang7dd2e102014-11-10 15:19:26 -05003940 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003941 {
Jamie Madill437fa652016-05-03 15:13:24 -04003942 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003943 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003944 }
3945
Jamie Madill0063c512014-08-25 15:47:53 -04003946 return true;
3947}
3948
He Yunchaoced53ae2016-11-29 15:00:51 +08003949bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003950{
3951 return ValidateGetUniformBase(context, program, location);
3952}
3953
He Yunchaoced53ae2016-11-29 15:00:51 +08003954bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003955{
Jamie Madill78f41802014-08-25 15:47:55 -04003956 return ValidateGetUniformBase(context, program, location);
3957}
3958
Geoff Langf41d0ee2016-10-07 13:04:23 -04003959static bool ValidateSizedGetUniform(Context *context,
3960 GLuint program,
3961 GLint location,
3962 GLsizei bufSize,
3963 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003964{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003965 if (length)
3966 {
3967 *length = 0;
3968 }
3969
Jamie Madill78f41802014-08-25 15:47:55 -04003970 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003971 {
Jamie Madill78f41802014-08-25 15:47:55 -04003972 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003973 }
3974
Geoff Langf41d0ee2016-10-07 13:04:23 -04003975 if (bufSize < 0)
3976 {
3977 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3978 return false;
3979 }
3980
Jamie Madilla502c742014-08-28 17:19:13 -04003981 gl::Program *programObject = context->getProgram(program);
3982 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003983
Jamie Madill78f41802014-08-25 15:47:55 -04003984 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003985 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003986 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003987 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003988 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003989 context->handleError(
3990 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003991 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003992 }
3993
Geoff Langf41d0ee2016-10-07 13:04:23 -04003994 if (length)
3995 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003996 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003997 }
3998
Jamie Madill0063c512014-08-25 15:47:53 -04003999 return true;
4000}
4001
He Yunchaoced53ae2016-11-29 15:00:51 +08004002bool ValidateGetnUniformfvEXT(Context *context,
4003 GLuint program,
4004 GLint location,
4005 GLsizei bufSize,
4006 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04004007{
Geoff Langf41d0ee2016-10-07 13:04:23 -04004008 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04004009}
4010
He Yunchaoced53ae2016-11-29 15:00:51 +08004011bool ValidateGetnUniformivEXT(Context *context,
4012 GLuint program,
4013 GLint location,
4014 GLsizei bufSize,
4015 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04004016{
Geoff Langf41d0ee2016-10-07 13:04:23 -04004017 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
4018}
4019
4020bool ValidateGetUniformfvRobustANGLE(Context *context,
4021 GLuint program,
4022 GLint location,
4023 GLsizei bufSize,
4024 GLsizei *length,
4025 GLfloat *params)
4026{
4027 if (!ValidateRobustEntryPoint(context, bufSize))
4028 {
4029 return false;
4030 }
4031
4032 // bufSize is validated in ValidateSizedGetUniform
4033 return ValidateSizedGetUniform(context, program, location, bufSize, length);
4034}
4035
4036bool ValidateGetUniformivRobustANGLE(Context *context,
4037 GLuint program,
4038 GLint location,
4039 GLsizei bufSize,
4040 GLsizei *length,
4041 GLint *params)
4042{
4043 if (!ValidateRobustEntryPoint(context, bufSize))
4044 {
4045 return false;
4046 }
4047
4048 // bufSize is validated in ValidateSizedGetUniform
4049 return ValidateSizedGetUniform(context, program, location, bufSize, length);
4050}
4051
4052bool ValidateGetUniformuivRobustANGLE(Context *context,
4053 GLuint program,
4054 GLint location,
4055 GLsizei bufSize,
4056 GLsizei *length,
4057 GLuint *params)
4058{
4059 if (!ValidateRobustEntryPoint(context, bufSize))
4060 {
4061 return false;
4062 }
4063
4064 if (context->getClientMajorVersion() < 3)
4065 {
4066 context->handleError(
4067 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
4068 return false;
4069 }
4070
4071 // bufSize is validated in ValidateSizedGetUniform
4072 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04004073}
4074
He Yunchaoced53ae2016-11-29 15:00:51 +08004075bool ValidateDiscardFramebufferBase(Context *context,
4076 GLenum target,
4077 GLsizei numAttachments,
4078 const GLenum *attachments,
4079 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07004080{
4081 if (numAttachments < 0)
4082 {
Jamie Madill437fa652016-05-03 15:13:24 -04004083 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07004084 return false;
4085 }
4086
4087 for (GLsizei i = 0; i < numAttachments; ++i)
4088 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02004089 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07004090 {
4091 if (defaultFramebuffer)
4092 {
Jamie Madill437fa652016-05-03 15:13:24 -04004093 context->handleError(Error(
4094 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07004095 return false;
4096 }
4097
4098 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
4099 {
Jamie Madill437fa652016-05-03 15:13:24 -04004100 context->handleError(Error(GL_INVALID_OPERATION,
4101 "Requested color attachment is greater than the maximum "
4102 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07004103 return false;
4104 }
4105 }
4106 else
4107 {
4108 switch (attachments[i])
4109 {
He Yunchaoced53ae2016-11-29 15:00:51 +08004110 case GL_DEPTH_ATTACHMENT:
4111 case GL_STENCIL_ATTACHMENT:
4112 case GL_DEPTH_STENCIL_ATTACHMENT:
4113 if (defaultFramebuffer)
4114 {
4115 context->handleError(
4116 Error(GL_INVALID_ENUM,
4117 "Invalid attachment when the default framebuffer is bound"));
4118 return false;
4119 }
4120 break;
4121 case GL_COLOR:
4122 case GL_DEPTH:
4123 case GL_STENCIL:
4124 if (!defaultFramebuffer)
4125 {
4126 context->handleError(
4127 Error(GL_INVALID_ENUM,
4128 "Invalid attachment when the default framebuffer is not bound"));
4129 return false;
4130 }
4131 break;
4132 default:
4133 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07004134 return false;
Austin Kinross08332632015-05-05 13:35:47 -07004135 }
4136 }
4137 }
4138
4139 return true;
4140}
4141
Austin Kinross6ee1e782015-05-29 17:05:37 -07004142bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
4143{
4144 // Note that debug marker calls must not set error state
4145
4146 if (length < 0)
4147 {
4148 return false;
4149 }
4150
4151 if (marker == nullptr)
4152 {
4153 return false;
4154 }
4155
4156 return true;
4157}
4158
4159bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
4160{
4161 // Note that debug marker calls must not set error state
4162
4163 if (length < 0)
4164 {
4165 return false;
4166 }
4167
4168 if (length > 0 && marker == nullptr)
4169 {
4170 return false;
4171 }
4172
4173 return true;
4174}
4175
Geoff Langdcab33b2015-07-21 13:03:16 -04004176bool ValidateEGLImageTargetTexture2DOES(Context *context,
4177 egl::Display *display,
4178 GLenum target,
4179 egl::Image *image)
4180{
Geoff Langa8406172015-07-21 16:53:39 -04004181 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4182 {
Jamie Madill437fa652016-05-03 15:13:24 -04004183 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004184 return false;
4185 }
4186
4187 switch (target)
4188 {
4189 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004190 if (!context->getExtensions().eglImage)
4191 {
4192 context->handleError(Error(
4193 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4194 }
4195 break;
4196
4197 case GL_TEXTURE_EXTERNAL_OES:
4198 if (!context->getExtensions().eglImageExternal)
4199 {
4200 context->handleError(Error(
4201 GL_INVALID_ENUM,
4202 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4203 }
Geoff Langa8406172015-07-21 16:53:39 -04004204 break;
4205
4206 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004207 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004208 return false;
4209 }
4210
4211 if (!display->isValidImage(image))
4212 {
Jamie Madill437fa652016-05-03 15:13:24 -04004213 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004214 return false;
4215 }
4216
4217 if (image->getSamples() > 0)
4218 {
Jamie Madill437fa652016-05-03 15:13:24 -04004219 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004220 "cannot create a 2D texture from a multisampled EGL image."));
4221 return false;
4222 }
4223
Jamie Madilla3944d42016-07-22 22:13:26 -04004224 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004225 if (!textureCaps.texturable)
4226 {
Jamie Madill437fa652016-05-03 15:13:24 -04004227 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004228 "EGL image internal format is not supported as a texture."));
4229 return false;
4230 }
4231
Geoff Langdcab33b2015-07-21 13:03:16 -04004232 return true;
4233}
4234
4235bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4236 egl::Display *display,
4237 GLenum target,
4238 egl::Image *image)
4239{
Geoff Langa8406172015-07-21 16:53:39 -04004240 if (!context->getExtensions().eglImage)
4241 {
Jamie Madill437fa652016-05-03 15:13:24 -04004242 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004243 return false;
4244 }
4245
4246 switch (target)
4247 {
4248 case GL_RENDERBUFFER:
4249 break;
4250
4251 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004252 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004253 return false;
4254 }
4255
4256 if (!display->isValidImage(image))
4257 {
Jamie Madill437fa652016-05-03 15:13:24 -04004258 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004259 return false;
4260 }
4261
Jamie Madilla3944d42016-07-22 22:13:26 -04004262 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004263 if (!textureCaps.renderable)
4264 {
Jamie Madill437fa652016-05-03 15:13:24 -04004265 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004266 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4267 return false;
4268 }
4269
Geoff Langdcab33b2015-07-21 13:03:16 -04004270 return true;
4271}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004272
4273bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4274{
Geoff Lang36167ab2015-12-07 10:27:14 -05004275 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004276 {
4277 // The default VAO should always exist
4278 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004279 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004280 return false;
4281 }
4282
4283 return true;
4284}
4285
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004286bool ValidateLinkProgram(Context *context, GLuint program)
4287{
4288 if (context->hasActiveTransformFeedback(program))
4289 {
4290 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004291 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004292 "Cannot link program while program is associated with an active "
4293 "transform feedback object."));
4294 return false;
4295 }
4296 return true;
4297}
4298
Geoff Langc5629752015-12-07 16:29:04 -05004299bool ValidateProgramBinaryBase(Context *context,
4300 GLuint program,
4301 GLenum binaryFormat,
4302 const void *binary,
4303 GLint length)
4304{
4305 Program *programObject = GetValidProgram(context, program);
4306 if (programObject == nullptr)
4307 {
4308 return false;
4309 }
4310
4311 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4312 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4313 programBinaryFormats.end())
4314 {
Jamie Madill437fa652016-05-03 15:13:24 -04004315 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004316 return false;
4317 }
4318
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004319 if (context->hasActiveTransformFeedback(program))
4320 {
4321 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004322 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004323 "Cannot change program binary while program is associated with "
4324 "an active transform feedback object."));
4325 return false;
4326 }
4327
Geoff Langc5629752015-12-07 16:29:04 -05004328 return true;
4329}
4330
4331bool ValidateGetProgramBinaryBase(Context *context,
4332 GLuint program,
4333 GLsizei bufSize,
4334 GLsizei *length,
4335 GLenum *binaryFormat,
4336 void *binary)
4337{
4338 Program *programObject = GetValidProgram(context, program);
4339 if (programObject == nullptr)
4340 {
4341 return false;
4342 }
4343
4344 if (!programObject->isLinked())
4345 {
Jamie Madill437fa652016-05-03 15:13:24 -04004346 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004347 return false;
4348 }
4349
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004350 if (context->getCaps().programBinaryFormats.empty())
4351 {
4352 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4353 return false;
4354 }
4355
Geoff Langc5629752015-12-07 16:29:04 -05004356 return true;
4357}
Jamie Madillc29968b2016-01-20 11:17:23 -05004358
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004359bool ValidateUseProgram(Context *context, GLuint program)
4360{
4361 if (program != 0)
4362 {
4363 Program *programObject = context->getProgram(program);
4364 if (!programObject)
4365 {
4366 // ES 3.1.0 section 7.3 page 72
4367 if (context->getShader(program))
4368 {
Jamie Madill437fa652016-05-03 15:13:24 -04004369 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004370 Error(GL_INVALID_OPERATION,
4371 "Attempted to use a single shader instead of a shader program."));
4372 return false;
4373 }
4374 else
4375 {
Jamie Madill437fa652016-05-03 15:13:24 -04004376 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004377 return false;
4378 }
4379 }
4380 if (!programObject->isLinked())
4381 {
Jamie Madill437fa652016-05-03 15:13:24 -04004382 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004383 return false;
4384 }
4385 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004386 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004387 {
4388 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004389 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004390 Error(GL_INVALID_OPERATION,
4391 "Cannot change active program while transform feedback is unpaused."));
4392 return false;
4393 }
4394
4395 return true;
4396}
4397
Jamie Madillc29968b2016-01-20 11:17:23 -05004398bool ValidateCopyTexImage2D(ValidationContext *context,
4399 GLenum target,
4400 GLint level,
4401 GLenum internalformat,
4402 GLint x,
4403 GLint y,
4404 GLsizei width,
4405 GLsizei height,
4406 GLint border)
4407{
Martin Radev1be913c2016-07-11 17:59:16 +03004408 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004409 {
4410 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4411 0, x, y, width, height, border);
4412 }
4413
Martin Radev1be913c2016-07-11 17:59:16 +03004414 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004415 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4416 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004417}
Jamie Madillc29968b2016-01-20 11:17:23 -05004418
4419bool ValidateFramebufferRenderbuffer(Context *context,
4420 GLenum target,
4421 GLenum attachment,
4422 GLenum renderbuffertarget,
4423 GLuint renderbuffer)
4424{
4425 if (!ValidFramebufferTarget(target) ||
4426 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4427 {
Jamie Madill437fa652016-05-03 15:13:24 -04004428 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004429 return false;
4430 }
4431
4432 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4433 renderbuffertarget, renderbuffer);
4434}
4435
4436bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4437{
4438 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4439 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4440 {
Jamie Madill437fa652016-05-03 15:13:24 -04004441 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004442 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4443 return false;
4444 }
4445
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004446 ASSERT(context->getGLState().getDrawFramebuffer());
4447 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004448 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4449
4450 // This should come first before the check for the default frame buffer
4451 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4452 // rather than INVALID_OPERATION
4453 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4454 {
4455 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4456
4457 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004458 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4459 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004460 {
4461 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004462 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4463 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4464 // 3.1 is still a bit ambiguous about the error, but future specs are
4465 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004466 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004467 return false;
4468 }
4469 else if (bufs[colorAttachment] >= maxColorAttachment)
4470 {
Jamie Madill437fa652016-05-03 15:13:24 -04004471 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004472 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004473 return false;
4474 }
4475 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4476 frameBufferId != 0)
4477 {
4478 // INVALID_OPERATION-GL is bound to buffer and ith argument
4479 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004480 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004481 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4482 return false;
4483 }
4484 }
4485
4486 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4487 // and n is not 1 or bufs is bound to value other than BACK and NONE
4488 if (frameBufferId == 0)
4489 {
4490 if (n != 1)
4491 {
Jamie Madill437fa652016-05-03 15:13:24 -04004492 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004493 "n must be 1 when GL is bound to the default framebuffer"));
4494 return false;
4495 }
4496
4497 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4498 {
Jamie Madill437fa652016-05-03 15:13:24 -04004499 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004500 GL_INVALID_OPERATION,
4501 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4502 return false;
4503 }
4504 }
4505
4506 return true;
4507}
4508
4509bool ValidateCopyTexSubImage2D(Context *context,
4510 GLenum target,
4511 GLint level,
4512 GLint xoffset,
4513 GLint yoffset,
4514 GLint x,
4515 GLint y,
4516 GLsizei width,
4517 GLsizei height)
4518{
Martin Radev1be913c2016-07-11 17:59:16 +03004519 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004520 {
4521 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4522 yoffset, x, y, width, height, 0);
4523 }
4524
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004525 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4526 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004527}
4528
Geoff Lang496c02d2016-10-20 11:38:11 -07004529bool ValidateGetBufferPointervBase(Context *context,
4530 GLenum target,
4531 GLenum pname,
4532 GLsizei *length,
4533 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004534{
Geoff Lang496c02d2016-10-20 11:38:11 -07004535 if (length)
4536 {
4537 *length = 0;
4538 }
4539
4540 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4541 {
4542 context->handleError(
4543 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004544 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004545 return false;
4546 }
4547
Olli Etuaho4f667482016-03-30 15:56:35 +03004548 if (!ValidBufferTarget(context, target))
4549 {
Jamie Madill437fa652016-05-03 15:13:24 -04004550 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004551 return false;
4552 }
4553
Geoff Lang496c02d2016-10-20 11:38:11 -07004554 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004555 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004556 case GL_BUFFER_MAP_POINTER:
4557 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004558
Geoff Lang496c02d2016-10-20 11:38:11 -07004559 default:
4560 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4561 return false;
4562 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004563
4564 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4565 // target bound to zero generate an INVALID_OPERATION error."
4566 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004567 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004568 {
Jamie Madill437fa652016-05-03 15:13:24 -04004569 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004570 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4571 return false;
4572 }
4573
Geoff Lang496c02d2016-10-20 11:38:11 -07004574 if (length)
4575 {
4576 *length = 1;
4577 }
4578
Olli Etuaho4f667482016-03-30 15:56:35 +03004579 return true;
4580}
4581
4582bool ValidateUnmapBufferBase(Context *context, GLenum target)
4583{
4584 if (!ValidBufferTarget(context, target))
4585 {
Jamie Madill437fa652016-05-03 15:13:24 -04004586 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004587 return false;
4588 }
4589
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004590 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004591
4592 if (buffer == nullptr || !buffer->isMapped())
4593 {
Jamie Madill437fa652016-05-03 15:13:24 -04004594 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004595 return false;
4596 }
4597
4598 return true;
4599}
4600
4601bool ValidateMapBufferRangeBase(Context *context,
4602 GLenum target,
4603 GLintptr offset,
4604 GLsizeiptr length,
4605 GLbitfield access)
4606{
4607 if (!ValidBufferTarget(context, target))
4608 {
Jamie Madill437fa652016-05-03 15:13:24 -04004609 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004610 return false;
4611 }
4612
4613 if (offset < 0 || length < 0)
4614 {
Jamie Madill437fa652016-05-03 15:13:24 -04004615 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004616 return false;
4617 }
4618
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004619 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004620
4621 if (!buffer)
4622 {
Jamie Madill437fa652016-05-03 15:13:24 -04004623 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004624 return false;
4625 }
4626
4627 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004628 CheckedNumeric<size_t> checkedOffset(offset);
4629 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004630
Jamie Madille2e406c2016-06-02 13:04:10 -04004631 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004632 {
Jamie Madill437fa652016-05-03 15:13:24 -04004633 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004634 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4635 return false;
4636 }
4637
4638 // Check for invalid bits in the mask
4639 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4640 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4641 GL_MAP_UNSYNCHRONIZED_BIT;
4642
4643 if (access & ~(allAccessBits))
4644 {
Jamie Madill437fa652016-05-03 15:13:24 -04004645 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004646 return false;
4647 }
4648
4649 if (length == 0)
4650 {
Jamie Madill437fa652016-05-03 15:13:24 -04004651 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004652 return false;
4653 }
4654
4655 if (buffer->isMapped())
4656 {
Jamie Madill437fa652016-05-03 15:13:24 -04004657 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004658 return false;
4659 }
4660
4661 // Check for invalid bit combinations
4662 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4663 {
Jamie Madill437fa652016-05-03 15:13:24 -04004664 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004665 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4666 return false;
4667 }
4668
4669 GLbitfield writeOnlyBits =
4670 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4671
4672 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4673 {
Jamie Madill437fa652016-05-03 15:13:24 -04004674 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004675 "Invalid access bits when mapping buffer for reading: 0x%X.",
4676 access));
4677 return false;
4678 }
4679
4680 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4681 {
Jamie Madill437fa652016-05-03 15:13:24 -04004682 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004683 GL_INVALID_OPERATION,
4684 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4685 return false;
4686 }
4687 return true;
4688}
4689
4690bool ValidateFlushMappedBufferRangeBase(Context *context,
4691 GLenum target,
4692 GLintptr offset,
4693 GLsizeiptr length)
4694{
4695 if (offset < 0 || length < 0)
4696 {
Jamie Madill437fa652016-05-03 15:13:24 -04004697 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004698 return false;
4699 }
4700
4701 if (!ValidBufferTarget(context, target))
4702 {
Jamie Madill437fa652016-05-03 15:13:24 -04004703 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004704 return false;
4705 }
4706
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004707 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004708
4709 if (buffer == nullptr)
4710 {
Jamie Madill437fa652016-05-03 15:13:24 -04004711 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004712 return false;
4713 }
4714
4715 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4716 {
Jamie Madill437fa652016-05-03 15:13:24 -04004717 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004718 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4719 return false;
4720 }
4721
4722 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004723 CheckedNumeric<size_t> checkedOffset(offset);
4724 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004725
Jamie Madille2e406c2016-06-02 13:04:10 -04004726 if (!checkedSize.IsValid() ||
4727 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004728 {
Jamie Madill437fa652016-05-03 15:13:24 -04004729 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004730 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4731 return false;
4732 }
4733
4734 return true;
4735}
4736
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004737bool ValidateGenerateMipmap(Context *context, GLenum target)
4738{
4739 if (!ValidTextureTarget(context, target))
4740 {
4741 context->handleError(Error(GL_INVALID_ENUM));
4742 return false;
4743 }
4744
4745 Texture *texture = context->getTargetTexture(target);
4746
4747 if (texture == nullptr)
4748 {
4749 context->handleError(Error(GL_INVALID_OPERATION));
4750 return false;
4751 }
4752
4753 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4754
4755 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4756 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4757 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4758 {
4759 context->handleError(Error(GL_INVALID_OPERATION));
4760 return false;
4761 }
4762
Jamie Madilla3944d42016-07-22 22:13:26 -04004763 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4764 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4765 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004766
4767 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4768 // unsized formats or that are color renderable and filterable. Since we do not track if
4769 // the texture was created with sized or unsized format (only sized formats are stored),
4770 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4771 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4772 // textures since they're the only texture format that can be created with unsized formats
4773 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4774 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004775 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4776 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004777 {
4778 context->handleError(Error(GL_INVALID_OPERATION));
4779 return false;
4780 }
4781
4782 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004783 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004784 {
4785 context->handleError(Error(GL_INVALID_OPERATION));
4786 return false;
4787 }
4788
4789 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004790 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004791 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4792 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4793 {
Geoff Lang55482a12016-11-21 16:54:01 -05004794 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004795 context->handleError(Error(GL_INVALID_OPERATION));
4796 return false;
4797 }
4798
4799 // Cube completeness check
4800 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4801 {
4802 context->handleError(Error(GL_INVALID_OPERATION));
4803 return false;
4804 }
4805
4806 return true;
4807}
4808
Olli Etuaho41997e72016-03-10 13:38:39 +02004809bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4810{
4811 return ValidateGenOrDelete(context, n);
4812}
4813
4814bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4815{
4816 return ValidateGenOrDelete(context, n);
4817}
4818
4819bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4820{
4821 return ValidateGenOrDelete(context, n);
4822}
4823
4824bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4825{
4826 return ValidateGenOrDelete(context, n);
4827}
4828
4829bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4830{
4831 return ValidateGenOrDelete(context, n);
4832}
4833
4834bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4835{
4836 return ValidateGenOrDelete(context, n);
4837}
4838
4839bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4840{
4841 return ValidateGenOrDelete(context, n);
4842}
4843
4844bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4845{
4846 return ValidateGenOrDelete(context, n);
4847}
4848
4849bool ValidateGenOrDelete(Context *context, GLint n)
4850{
4851 if (n < 0)
4852 {
Jamie Madill437fa652016-05-03 15:13:24 -04004853 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004854 return false;
4855 }
4856 return true;
4857}
4858
Geoff Langf41a7152016-09-19 15:11:17 -04004859bool ValidateEnable(Context *context, GLenum cap)
4860{
4861 if (!ValidCap(context, cap, false))
4862 {
4863 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4864 return false;
4865 }
4866
4867 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4868 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4869 {
4870 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4871 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4872
4873 // We also output an error message to the debugger window if tracing is active, so that
4874 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05004875 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04004876 return false;
4877 }
4878
4879 return true;
4880}
4881
4882bool ValidateDisable(Context *context, GLenum cap)
4883{
4884 if (!ValidCap(context, cap, false))
4885 {
4886 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4887 return false;
4888 }
4889
4890 return true;
4891}
4892
4893bool ValidateIsEnabled(Context *context, GLenum cap)
4894{
4895 if (!ValidCap(context, cap, true))
4896 {
4897 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4898 return false;
4899 }
4900
4901 return true;
4902}
4903
Geoff Langff5b2d52016-09-07 11:32:23 -04004904bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4905{
4906 if (!context->getExtensions().robustClientMemory)
4907 {
4908 context->handleError(
4909 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4910 return false;
4911 }
4912
4913 if (bufSize < 0)
4914 {
4915 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4916 return false;
4917 }
4918
4919 return true;
4920}
4921
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004922bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4923{
4924 if (bufSize < numParams)
4925 {
4926 context->handleError(Error(GL_INVALID_OPERATION,
4927 "%u parameters are required but %i were provided.", numParams,
4928 bufSize));
4929 return false;
4930 }
4931
4932 return true;
4933}
4934
Geoff Langff5b2d52016-09-07 11:32:23 -04004935bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4936 GLenum target,
4937 GLenum attachment,
4938 GLenum pname,
4939 GLsizei *numParams)
4940{
4941 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4942 *numParams = 1;
4943
4944 if (!ValidFramebufferTarget(target))
4945 {
4946 context->handleError(Error(GL_INVALID_ENUM));
4947 return false;
4948 }
4949
4950 int clientVersion = context->getClientMajorVersion();
4951
4952 switch (pname)
4953 {
4954 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4955 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4956 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4957 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4958 break;
4959
4960 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4961 if (clientVersion < 3 && !context->getExtensions().sRGB)
4962 {
4963 context->handleError(Error(GL_INVALID_ENUM));
4964 return false;
4965 }
4966 break;
4967
4968 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4969 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4970 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4971 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4972 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4973 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4974 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4975 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4976 if (clientVersion < 3)
4977 {
4978 context->handleError(Error(GL_INVALID_ENUM));
4979 return false;
4980 }
4981 break;
4982
4983 default:
4984 context->handleError(Error(GL_INVALID_ENUM));
4985 return false;
4986 }
4987
4988 // Determine if the attachment is a valid enum
4989 switch (attachment)
4990 {
4991 case GL_BACK:
4992 case GL_FRONT:
4993 case GL_DEPTH:
4994 case GL_STENCIL:
4995 case GL_DEPTH_STENCIL_ATTACHMENT:
4996 if (clientVersion < 3)
4997 {
4998 context->handleError(Error(GL_INVALID_ENUM));
4999 return false;
5000 }
5001 break;
5002
5003 case GL_DEPTH_ATTACHMENT:
5004 case GL_STENCIL_ATTACHMENT:
5005 break;
5006
5007 default:
5008 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
5009 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
5010 {
5011 context->handleError(Error(GL_INVALID_ENUM));
5012 return false;
5013 }
5014 break;
5015 }
5016
5017 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
5018 ASSERT(framebuffer);
5019
5020 if (framebuffer->id() == 0)
5021 {
5022 if (clientVersion < 3)
5023 {
5024 context->handleError(Error(GL_INVALID_OPERATION));
5025 return false;
5026 }
5027
5028 switch (attachment)
5029 {
5030 case GL_BACK:
5031 case GL_DEPTH:
5032 case GL_STENCIL:
5033 break;
5034
5035 default:
5036 context->handleError(Error(GL_INVALID_OPERATION));
5037 return false;
5038 }
5039 }
5040 else
5041 {
5042 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
5043 {
5044 // Valid attachment query
5045 }
5046 else
5047 {
5048 switch (attachment)
5049 {
5050 case GL_DEPTH_ATTACHMENT:
5051 case GL_STENCIL_ATTACHMENT:
5052 break;
5053
5054 case GL_DEPTH_STENCIL_ATTACHMENT:
5055 if (!framebuffer->hasValidDepthStencil())
5056 {
5057 context->handleError(Error(GL_INVALID_OPERATION));
5058 return false;
5059 }
5060 break;
5061
5062 default:
5063 context->handleError(Error(GL_INVALID_OPERATION));
5064 return false;
5065 }
5066 }
5067 }
5068
5069 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
5070 if (attachmentObject)
5071 {
5072 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
5073 attachmentObject->type() == GL_TEXTURE ||
5074 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
5075
5076 switch (pname)
5077 {
5078 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5079 if (attachmentObject->type() != GL_RENDERBUFFER &&
5080 attachmentObject->type() != GL_TEXTURE)
5081 {
5082 context->handleError(Error(GL_INVALID_ENUM));
5083 return false;
5084 }
5085 break;
5086
5087 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
5088 if (attachmentObject->type() != GL_TEXTURE)
5089 {
5090 context->handleError(Error(GL_INVALID_ENUM));
5091 return false;
5092 }
5093 break;
5094
5095 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
5096 if (attachmentObject->type() != GL_TEXTURE)
5097 {
5098 context->handleError(Error(GL_INVALID_ENUM));
5099 return false;
5100 }
5101 break;
5102
5103 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
5104 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
5105 {
5106 context->handleError(Error(GL_INVALID_OPERATION));
5107 return false;
5108 }
5109 break;
5110
5111 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
5112 if (attachmentObject->type() != GL_TEXTURE)
5113 {
5114 context->handleError(Error(GL_INVALID_ENUM));
5115 return false;
5116 }
5117 break;
5118
5119 default:
5120 break;
5121 }
5122 }
5123 else
5124 {
5125 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
5126 // is NONE, then querying any other pname will generate INVALID_ENUM.
5127
5128 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
5129 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
5130 // INVALID_OPERATION for all other pnames
5131
5132 switch (pname)
5133 {
5134 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5135 break;
5136
5137 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5138 if (clientVersion < 3)
5139 {
5140 context->handleError(Error(GL_INVALID_ENUM));
5141 return false;
5142 }
5143 break;
5144
5145 default:
5146 if (clientVersion < 3)
5147 {
5148 context->handleError(Error(GL_INVALID_ENUM));
5149 return false;
5150 }
5151 else
5152 {
5153 context->handleError(Error(GL_INVALID_OPERATION));
5154 return false;
5155 }
5156 }
5157 }
5158
5159 return true;
5160}
5161
5162bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5163 GLenum target,
5164 GLenum attachment,
5165 GLenum pname,
5166 GLsizei bufSize,
5167 GLsizei *numParams)
5168{
5169 if (!ValidateRobustEntryPoint(context, bufSize))
5170 {
5171 return false;
5172 }
5173
5174 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5175 {
5176 return false;
5177 }
5178
5179 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5180 {
5181 return false;
5182 }
5183
5184 return true;
5185}
5186
5187bool ValidateGetBufferParameteriv(ValidationContext *context,
5188 GLenum target,
5189 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005190 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005191{
Geoff Langebebe1c2016-10-14 12:01:31 -04005192 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005193}
5194
5195bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5196 GLenum target,
5197 GLenum pname,
5198 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005199 GLsizei *length,
5200 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005201{
5202 if (!ValidateRobustEntryPoint(context, bufSize))
5203 {
5204 return false;
5205 }
5206
Geoff Langebebe1c2016-10-14 12:01:31 -04005207 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005208 {
5209 return false;
5210 }
5211
Geoff Langebebe1c2016-10-14 12:01:31 -04005212 if (!ValidateRobustBufferSize(context, bufSize, *length))
5213 {
5214 return false;
5215 }
5216
5217 return true;
5218}
5219
5220bool ValidateGetBufferParameteri64v(ValidationContext *context,
5221 GLenum target,
5222 GLenum pname,
5223 GLint64 *params)
5224{
5225 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5226}
5227
5228bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5229 GLenum target,
5230 GLenum pname,
5231 GLsizei bufSize,
5232 GLsizei *length,
5233 GLint64 *params)
5234{
5235 if (!ValidateRobustEntryPoint(context, bufSize))
5236 {
5237 return false;
5238 }
5239
5240 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5241 {
5242 return false;
5243 }
5244
5245 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005246 {
5247 return false;
5248 }
5249
5250 return true;
5251}
5252
5253bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5254{
5255 // Currently, all GetProgramiv queries return 1 parameter
5256 *numParams = 1;
5257
5258 Program *programObject = GetValidProgram(context, program);
5259 if (!programObject)
5260 {
5261 return false;
5262 }
5263
5264 switch (pname)
5265 {
5266 case GL_DELETE_STATUS:
5267 case GL_LINK_STATUS:
5268 case GL_VALIDATE_STATUS:
5269 case GL_INFO_LOG_LENGTH:
5270 case GL_ATTACHED_SHADERS:
5271 case GL_ACTIVE_ATTRIBUTES:
5272 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5273 case GL_ACTIVE_UNIFORMS:
5274 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5275 break;
5276
5277 case GL_PROGRAM_BINARY_LENGTH:
5278 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5279 {
5280 context->handleError(Error(GL_INVALID_ENUM,
5281 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5282 "GL_OES_get_program_binary or ES 3.0."));
5283 return false;
5284 }
5285 break;
5286
5287 case GL_ACTIVE_UNIFORM_BLOCKS:
5288 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5289 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5290 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5291 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5292 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5293 if (context->getClientMajorVersion() < 3)
5294 {
5295 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5296 return false;
5297 }
5298 break;
5299
Yunchao He61afff12017-03-14 15:34:03 +08005300 case GL_PROGRAM_SEPARABLE:
5301 if (context->getClientVersion() < Version(3, 1))
5302 {
5303 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.1."));
5304 return false;
5305 }
5306 break;
5307
Geoff Langff5b2d52016-09-07 11:32:23 -04005308 default:
5309 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5310 return false;
5311 }
5312
5313 return true;
5314}
5315
5316bool ValidateGetProgramivRobustANGLE(Context *context,
5317 GLuint program,
5318 GLenum pname,
5319 GLsizei bufSize,
5320 GLsizei *numParams)
5321{
5322 if (!ValidateRobustEntryPoint(context, bufSize))
5323 {
5324 return false;
5325 }
5326
5327 if (!ValidateGetProgramiv(context, program, pname, numParams))
5328 {
5329 return false;
5330 }
5331
5332 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5333 {
5334 return false;
5335 }
5336
5337 return true;
5338}
5339
Geoff Lang740d9022016-10-07 11:20:52 -04005340bool ValidateGetRenderbufferParameteriv(Context *context,
5341 GLenum target,
5342 GLenum pname,
5343 GLint *params)
5344{
5345 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5346}
5347
5348bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5349 GLenum target,
5350 GLenum pname,
5351 GLsizei bufSize,
5352 GLsizei *length,
5353 GLint *params)
5354{
5355 if (!ValidateRobustEntryPoint(context, bufSize))
5356 {
5357 return false;
5358 }
5359
5360 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5361 {
5362 return false;
5363 }
5364
5365 if (!ValidateRobustBufferSize(context, bufSize, *length))
5366 {
5367 return false;
5368 }
5369
5370 return true;
5371}
5372
Geoff Langd7d0ed32016-10-07 11:33:51 -04005373bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5374{
5375 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5376}
5377
5378bool ValidateGetShaderivRobustANGLE(Context *context,
5379 GLuint shader,
5380 GLenum pname,
5381 GLsizei bufSize,
5382 GLsizei *length,
5383 GLint *params)
5384{
5385 if (!ValidateRobustEntryPoint(context, bufSize))
5386 {
5387 return false;
5388 }
5389
5390 if (!ValidateGetShaderivBase(context, shader, pname, length))
5391 {
5392 return false;
5393 }
5394
5395 if (!ValidateRobustBufferSize(context, bufSize, *length))
5396 {
5397 return false;
5398 }
5399
5400 return true;
5401}
5402
Geoff Langc1984ed2016-10-07 12:41:00 -04005403bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5404{
5405 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5406}
5407
5408bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5409 GLenum target,
5410 GLenum pname,
5411 GLsizei bufSize,
5412 GLsizei *length,
5413 GLfloat *params)
5414{
5415 if (!ValidateRobustEntryPoint(context, bufSize))
5416 {
5417 return false;
5418 }
5419
5420 if (!ValidateGetTexParameterBase(context, target, pname, length))
5421 {
5422 return false;
5423 }
5424
5425 if (!ValidateRobustBufferSize(context, bufSize, *length))
5426 {
5427 return false;
5428 }
5429
5430 return true;
5431}
5432
5433bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5434{
5435 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5436}
5437
5438bool ValidateGetTexParameterivRobustANGLE(Context *context,
5439 GLenum target,
5440 GLenum pname,
5441 GLsizei bufSize,
5442 GLsizei *length,
5443 GLint *params)
5444{
5445 if (!ValidateRobustEntryPoint(context, bufSize))
5446 {
5447 return false;
5448 }
5449
5450 if (!ValidateGetTexParameterBase(context, target, pname, length))
5451 {
5452 return false;
5453 }
5454
5455 if (!ValidateRobustBufferSize(context, bufSize, *length))
5456 {
5457 return false;
5458 }
5459
5460 return true;
5461}
5462
5463bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5464{
5465 return ValidateTexParameterBase(context, target, pname, -1, &param);
5466}
5467
5468bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5469{
5470 return ValidateTexParameterBase(context, target, pname, -1, params);
5471}
5472
5473bool ValidateTexParameterfvRobustANGLE(Context *context,
5474 GLenum target,
5475 GLenum pname,
5476 GLsizei bufSize,
5477 const GLfloat *params)
5478{
5479 if (!ValidateRobustEntryPoint(context, bufSize))
5480 {
5481 return false;
5482 }
5483
5484 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5485}
5486
5487bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5488{
5489 return ValidateTexParameterBase(context, target, pname, -1, &param);
5490}
5491
5492bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5493{
5494 return ValidateTexParameterBase(context, target, pname, -1, params);
5495}
5496
5497bool ValidateTexParameterivRobustANGLE(Context *context,
5498 GLenum target,
5499 GLenum pname,
5500 GLsizei bufSize,
5501 const GLint *params)
5502{
5503 if (!ValidateRobustEntryPoint(context, bufSize))
5504 {
5505 return false;
5506 }
5507
5508 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5509}
5510
5511bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5512{
5513 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5514}
5515
5516bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5517 GLuint sampler,
5518 GLenum pname,
5519 GLuint bufSize,
5520 GLsizei *length,
5521 GLfloat *params)
5522{
5523 if (!ValidateRobustEntryPoint(context, bufSize))
5524 {
5525 return false;
5526 }
5527
5528 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5529 {
5530 return false;
5531 }
5532
5533 if (!ValidateRobustBufferSize(context, bufSize, *length))
5534 {
5535 return false;
5536 }
5537
5538 return true;
5539}
5540
5541bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5542{
5543 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5544}
5545
5546bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5547 GLuint sampler,
5548 GLenum pname,
5549 GLuint bufSize,
5550 GLsizei *length,
5551 GLint *params)
5552{
5553 if (!ValidateRobustEntryPoint(context, bufSize))
5554 {
5555 return false;
5556 }
5557
5558 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5559 {
5560 return false;
5561 }
5562
5563 if (!ValidateRobustBufferSize(context, bufSize, *length))
5564 {
5565 return false;
5566 }
5567
5568 return true;
5569}
5570
5571bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5572{
5573 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5574}
5575
5576bool ValidateSamplerParameterfv(Context *context,
5577 GLuint sampler,
5578 GLenum pname,
5579 const GLfloat *params)
5580{
5581 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5582}
5583
5584bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5585 GLuint sampler,
5586 GLenum pname,
5587 GLsizei bufSize,
5588 const GLfloat *params)
5589{
5590 if (!ValidateRobustEntryPoint(context, bufSize))
5591 {
5592 return false;
5593 }
5594
5595 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5596}
5597
5598bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5599{
5600 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5601}
5602
5603bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5604{
5605 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5606}
5607
5608bool ValidateSamplerParameterivRobustANGLE(Context *context,
5609 GLuint sampler,
5610 GLenum pname,
5611 GLsizei bufSize,
5612 const GLint *params)
5613{
5614 if (!ValidateRobustEntryPoint(context, bufSize))
5615 {
5616 return false;
5617 }
5618
5619 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5620}
5621
Geoff Lang0b031062016-10-13 14:30:04 -04005622bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5623{
5624 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5625}
5626
5627bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5628 GLuint index,
5629 GLenum pname,
5630 GLsizei bufSize,
5631 GLsizei *length,
5632 GLfloat *params)
5633{
5634 if (!ValidateRobustEntryPoint(context, bufSize))
5635 {
5636 return false;
5637 }
5638
5639 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5640 {
5641 return false;
5642 }
5643
5644 if (!ValidateRobustBufferSize(context, bufSize, *length))
5645 {
5646 return false;
5647 }
5648
5649 return true;
5650}
5651
5652bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5653{
5654 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5655}
5656
5657bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5658 GLuint index,
5659 GLenum pname,
5660 GLsizei bufSize,
5661 GLsizei *length,
5662 GLint *params)
5663{
5664 if (!ValidateRobustEntryPoint(context, bufSize))
5665 {
5666 return false;
5667 }
5668
5669 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5670 {
5671 return false;
5672 }
5673
5674 if (!ValidateRobustBufferSize(context, bufSize, *length))
5675 {
5676 return false;
5677 }
5678
5679 return true;
5680}
5681
5682bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5683{
5684 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5685}
5686
5687bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5688 GLuint index,
5689 GLenum pname,
5690 GLsizei bufSize,
5691 GLsizei *length,
5692 void **pointer)
5693{
5694 if (!ValidateRobustEntryPoint(context, bufSize))
5695 {
5696 return false;
5697 }
5698
5699 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5700 {
5701 return false;
5702 }
5703
5704 if (!ValidateRobustBufferSize(context, bufSize, *length))
5705 {
5706 return false;
5707 }
5708
5709 return true;
5710}
5711
5712bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5713{
5714 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5715}
5716
5717bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5718 GLuint index,
5719 GLenum pname,
5720 GLsizei bufSize,
5721 GLsizei *length,
5722 GLint *params)
5723{
5724 if (!ValidateRobustEntryPoint(context, bufSize))
5725 {
5726 return false;
5727 }
5728
5729 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5730 {
5731 return false;
5732 }
5733
5734 if (!ValidateRobustBufferSize(context, bufSize, *length))
5735 {
5736 return false;
5737 }
5738
5739 return true;
5740}
5741
5742bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5743{
5744 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5745}
5746
5747bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5748 GLuint index,
5749 GLenum pname,
5750 GLsizei bufSize,
5751 GLsizei *length,
5752 GLuint *params)
5753{
5754 if (!ValidateRobustEntryPoint(context, bufSize))
5755 {
5756 return false;
5757 }
5758
5759 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5760 {
5761 return false;
5762 }
5763
5764 if (!ValidateRobustBufferSize(context, bufSize, *length))
5765 {
5766 return false;
5767 }
5768
5769 return true;
5770}
5771
Geoff Lang6899b872016-10-14 11:30:13 -04005772bool ValidateGetActiveUniformBlockiv(Context *context,
5773 GLuint program,
5774 GLuint uniformBlockIndex,
5775 GLenum pname,
5776 GLint *params)
5777{
5778 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5779}
5780
5781bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5782 GLuint program,
5783 GLuint uniformBlockIndex,
5784 GLenum pname,
5785 GLsizei bufSize,
5786 GLsizei *length,
5787 GLint *params)
5788{
5789 if (!ValidateRobustEntryPoint(context, bufSize))
5790 {
5791 return false;
5792 }
5793
5794 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5795 {
5796 return false;
5797 }
5798
5799 if (!ValidateRobustBufferSize(context, bufSize, *length))
5800 {
5801 return false;
5802 }
5803
5804 return true;
5805}
5806
Geoff Lang0a9661f2016-10-20 10:59:20 -07005807bool ValidateGetInternalFormativ(Context *context,
5808 GLenum target,
5809 GLenum internalformat,
5810 GLenum pname,
5811 GLsizei bufSize,
5812 GLint *params)
5813{
5814 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5815 nullptr);
5816}
5817
5818bool ValidateGetInternalFormativRobustANGLE(Context *context,
5819 GLenum target,
5820 GLenum internalformat,
5821 GLenum pname,
5822 GLsizei bufSize,
5823 GLsizei *length,
5824 GLint *params)
5825{
5826 if (!ValidateRobustEntryPoint(context, bufSize))
5827 {
5828 return false;
5829 }
5830
5831 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5832 {
5833 return false;
5834 }
5835
5836 if (!ValidateRobustBufferSize(context, bufSize, *length))
5837 {
5838 return false;
5839 }
5840
5841 return true;
5842}
5843
Shao80957d92017-02-20 21:25:59 +08005844bool ValidateVertexFormatBase(ValidationContext *context,
5845 GLuint attribIndex,
5846 GLint size,
5847 GLenum type,
5848 GLboolean pureInteger)
5849{
5850 const Caps &caps = context->getCaps();
5851 if (attribIndex >= caps.maxVertexAttributes)
5852 {
5853 context->handleError(
5854 Error(GL_INVALID_VALUE, "attribindex must be smaller than MAX_VERTEX_ATTRIBS."));
5855 return false;
5856 }
5857
5858 if (size < 1 || size > 4)
5859 {
5860 context->handleError(Error(GL_INVALID_VALUE, "size must be between one and four."));
5861 }
5862
5863 switch (type)
5864 {
5865 case GL_BYTE:
5866 case GL_UNSIGNED_BYTE:
5867 case GL_SHORT:
5868 case GL_UNSIGNED_SHORT:
5869 break;
5870
5871 case GL_INT:
5872 case GL_UNSIGNED_INT:
5873 if (context->getClientMajorVersion() < 3)
5874 {
5875 context->handleError(
5876 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
5877 return false;
5878 }
5879 break;
5880
5881 case GL_FIXED:
5882 case GL_FLOAT:
5883 if (pureInteger)
5884 {
5885 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
5886 return false;
5887 }
5888 break;
5889
5890 case GL_HALF_FLOAT:
5891 if (context->getClientMajorVersion() < 3)
5892 {
5893 context->handleError(
5894 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
5895 return false;
5896 }
5897 if (pureInteger)
5898 {
5899 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
5900 return false;
5901 }
5902 break;
5903
5904 case GL_INT_2_10_10_10_REV:
5905 case GL_UNSIGNED_INT_2_10_10_10_REV:
5906 if (context->getClientMajorVersion() < 3)
5907 {
5908 context->handleError(
5909 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
5910 return false;
5911 }
5912 if (pureInteger)
5913 {
5914 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
5915 return false;
5916 }
5917 if (size != 4)
5918 {
5919 context->handleError(Error(GL_INVALID_OPERATION,
5920 "Type is INT_2_10_10_10_REV or "
5921 "UNSIGNED_INT_2_10_10_10_REV and size is not 4."));
5922 return false;
5923 }
5924 break;
5925
5926 default:
5927 context->handleError(Error(GL_INVALID_ENUM, "Invalid vertex type."));
5928 return false;
5929 }
5930
5931 return true;
5932}
5933
Geoff Lang76e65652017-03-27 14:58:02 -04005934// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5935// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5936// specified clear value and the type of a buffer that is being cleared generates an
5937// INVALID_OPERATION error instead of producing undefined results
5938bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
5939 GLint drawbuffer,
5940 const GLenum *validComponentTypes,
5941 size_t validComponentTypeCount)
5942{
5943 const FramebufferAttachment *attachment =
5944 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5945 if (attachment)
5946 {
5947 GLenum componentType = attachment->getFormat().info->componentType;
5948 const GLenum *end = validComponentTypes + validComponentTypeCount;
5949 if (std::find(validComponentTypes, end, componentType) == end)
5950 {
5951 context->handleError(
5952 Error(GL_INVALID_OPERATION,
5953 "No defined conversion between clear value and attachment format."));
5954 return false;
5955 }
5956 }
5957
5958 return true;
5959}
5960
Jamie Madillc29968b2016-01-20 11:17:23 -05005961} // namespace gl