blob: fd4c53d53ff99ba4aff0a03276bfd7927aaa5781 [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,
Jamie Madill876429b2017-04-20 15:46:24 -0400238 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400239{
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
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400261 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400262 {
263 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
264 return false;
265 }
266
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400267 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400268 {
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();
Geoff Langca271392017-04-05 12:30:00 -0400295 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
Geoff Lang62fce5b2016-09-30 10:46:35 -0400296
Geoff Lang62fce5b2016-09-30 10:46:35 -0400297 bool validFormatTypeCombination =
Geoff Langca271392017-04-05 12:30:00 -0400298 ValidReadPixelsFormatType(context, currentComponentType, format, type);
Geoff Lang62fce5b2016-09-30 10:46:35 -0400299
300 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
301 {
302 context->handleError(Error(GL_INVALID_OPERATION));
303 return false;
304 }
305
306 // Check for pixel pack buffer related API errors
307 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
308 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
309 {
310 // ...the buffer object's data store is currently mapped.
311 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
312 return false;
313 }
314
315 // .. the data would be packed to the buffer object such that the memory writes required
316 // would exceed the data store size.
Geoff Langca271392017-04-05 12:30:00 -0400317 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
Geoff Lang62fce5b2016-09-30 10:46:35 -0400318 const gl::Extents size(width, height, 1);
319 const auto &pack = context->getGLState().getPackState();
320
321 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
322 if (endByteOrErr.isError())
323 {
324 context->handleError(endByteOrErr.getError());
325 return false;
326 }
327
328 size_t endByte = endByteOrErr.getResult();
329 if (bufSize >= 0)
330 {
Geoff Lange93daba2017-03-30 13:54:40 -0400331 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400332 {
333 context->handleError(
334 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
335 return false;
336 }
337 }
338
339 if (pixelPackBuffer != nullptr)
340 {
341 CheckedNumeric<size_t> checkedEndByte(endByte);
342 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
343 checkedEndByte += checkedOffset;
344
345 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
346 {
347 // Overflow past the end of the buffer
348 context->handleError(
349 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
350 return false;
351 }
352 }
353
Geoff Lange93daba2017-03-30 13:54:40 -0400354 if (pixelPackBuffer == nullptr && length != nullptr)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400355 {
356 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
357 {
358 context->handleError(
359 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
360 return false;
361 }
362
363 *length = static_cast<GLsizei>(endByte);
364 }
365
Geoff Lange93daba2017-03-30 13:54:40 -0400366 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
367 angle::CheckedNumeric<int> clippedExtent(length);
368 if (start < 0)
369 {
370 // "subtract" the area that is less than 0
371 clippedExtent += start;
372 }
373
374 const int readExtent = start + length;
375 if (readExtent > bufferSize)
376 {
377 // Subtract the region to the right of the read buffer
378 clippedExtent -= (readExtent - bufferSize);
379 }
380
381 if (!clippedExtent.IsValid())
382 {
383 return 0;
384 }
385
386 return std::max(clippedExtent.ValueOrDie(), 0);
387 };
388
389 if (columns != nullptr)
390 {
391 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
392 }
393
394 if (rows != nullptr)
395 {
396 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
397 }
398
Geoff Lang62fce5b2016-09-30 10:46:35 -0400399 return true;
400}
401
Geoff Lang740d9022016-10-07 11:20:52 -0400402bool ValidateGetRenderbufferParameterivBase(Context *context,
403 GLenum target,
404 GLenum pname,
405 GLsizei *length)
406{
407 if (length)
408 {
409 *length = 0;
410 }
411
412 if (target != GL_RENDERBUFFER)
413 {
414 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
415 return false;
416 }
417
418 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
419 if (renderbuffer == nullptr)
420 {
421 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
422 return false;
423 }
424
425 switch (pname)
426 {
427 case GL_RENDERBUFFER_WIDTH:
428 case GL_RENDERBUFFER_HEIGHT:
429 case GL_RENDERBUFFER_INTERNAL_FORMAT:
430 case GL_RENDERBUFFER_RED_SIZE:
431 case GL_RENDERBUFFER_GREEN_SIZE:
432 case GL_RENDERBUFFER_BLUE_SIZE:
433 case GL_RENDERBUFFER_ALPHA_SIZE:
434 case GL_RENDERBUFFER_DEPTH_SIZE:
435 case GL_RENDERBUFFER_STENCIL_SIZE:
436 break;
437
438 case GL_RENDERBUFFER_SAMPLES_ANGLE:
439 if (!context->getExtensions().framebufferMultisample)
440 {
441 context->handleError(
442 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
443 return false;
444 }
445 break;
446
447 default:
448 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
449 return false;
450 }
451
452 if (length)
453 {
454 *length = 1;
455 }
456 return true;
457}
458
Geoff Langd7d0ed32016-10-07 11:33:51 -0400459bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
460{
461 if (length)
462 {
463 *length = 0;
464 }
465
466 if (GetValidShader(context, shader) == nullptr)
467 {
468 return false;
469 }
470
471 switch (pname)
472 {
473 case GL_SHADER_TYPE:
474 case GL_DELETE_STATUS:
475 case GL_COMPILE_STATUS:
476 case GL_INFO_LOG_LENGTH:
477 case GL_SHADER_SOURCE_LENGTH:
478 break;
479
480 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
481 if (!context->getExtensions().translatedShaderSource)
482 {
483 context->handleError(
484 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
485 return false;
486 }
487 break;
488
489 default:
490 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
491 return false;
492 }
493
494 if (length)
495 {
496 *length = 1;
497 }
498 return true;
499}
500
Geoff Langc1984ed2016-10-07 12:41:00 -0400501bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
502{
503 if (length)
504 {
505 *length = 0;
506 }
507
508 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
509 {
510 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
511 return false;
512 }
513
514 if (context->getTargetTexture(target) == nullptr)
515 {
516 // Should only be possible for external textures
517 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
518 return false;
519 }
520
521 switch (pname)
522 {
523 case GL_TEXTURE_MAG_FILTER:
524 case GL_TEXTURE_MIN_FILTER:
525 case GL_TEXTURE_WRAP_S:
526 case GL_TEXTURE_WRAP_T:
527 break;
528
529 case GL_TEXTURE_USAGE_ANGLE:
530 if (!context->getExtensions().textureUsage)
531 {
532 context->handleError(
533 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
534 return false;
535 }
536 break;
537
538 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
539 if (!context->getExtensions().textureFilterAnisotropic)
540 {
541 context->handleError(
542 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
543 return false;
544 }
545 break;
546
547 case GL_TEXTURE_IMMUTABLE_FORMAT:
548 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
549 {
550 context->handleError(
551 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
552 return false;
553 }
554 break;
555
556 case GL_TEXTURE_WRAP_R:
557 case GL_TEXTURE_IMMUTABLE_LEVELS:
558 case GL_TEXTURE_SWIZZLE_R:
559 case GL_TEXTURE_SWIZZLE_G:
560 case GL_TEXTURE_SWIZZLE_B:
561 case GL_TEXTURE_SWIZZLE_A:
562 case GL_TEXTURE_BASE_LEVEL:
563 case GL_TEXTURE_MAX_LEVEL:
564 case GL_TEXTURE_MIN_LOD:
565 case GL_TEXTURE_MAX_LOD:
566 case GL_TEXTURE_COMPARE_MODE:
567 case GL_TEXTURE_COMPARE_FUNC:
568 if (context->getClientMajorVersion() < 3)
569 {
570 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
571 return false;
572 }
573 break;
574
Geoff Lang81c6b572016-10-19 14:07:52 -0700575 case GL_TEXTURE_SRGB_DECODE_EXT:
576 if (!context->getExtensions().textureSRGBDecode)
577 {
578 context->handleError(
579 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
580 return false;
581 }
582 break;
583
Geoff Langc1984ed2016-10-07 12:41:00 -0400584 default:
585 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
586 return false;
587 }
588
589 if (length)
590 {
591 *length = 1;
592 }
593 return true;
594}
595
596template <typename ParamType>
597bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
598{
599 switch (ConvertToGLenum(params[0]))
600 {
601 case GL_CLAMP_TO_EDGE:
602 break;
603
604 case GL_REPEAT:
605 case GL_MIRRORED_REPEAT:
606 if (isExternalTextureTarget)
607 {
608 // OES_EGL_image_external specifies this error.
609 context->handleError(Error(
610 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
611 return false;
612 }
613 break;
614
615 default:
616 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
617 return false;
618 }
619
620 return true;
621}
622
623template <typename ParamType>
624bool ValidateTextureMinFilterValue(Context *context,
625 ParamType *params,
626 bool isExternalTextureTarget)
627{
628 switch (ConvertToGLenum(params[0]))
629 {
630 case GL_NEAREST:
631 case GL_LINEAR:
632 break;
633
634 case GL_NEAREST_MIPMAP_NEAREST:
635 case GL_LINEAR_MIPMAP_NEAREST:
636 case GL_NEAREST_MIPMAP_LINEAR:
637 case GL_LINEAR_MIPMAP_LINEAR:
638 if (isExternalTextureTarget)
639 {
640 // OES_EGL_image_external specifies this error.
641 context->handleError(
642 Error(GL_INVALID_ENUM,
643 "external textures only support NEAREST and LINEAR filtering"));
644 return false;
645 }
646 break;
647
648 default:
649 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
650 return false;
651 }
652
653 return true;
654}
655
656template <typename ParamType>
657bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
658{
659 switch (ConvertToGLenum(params[0]))
660 {
661 case GL_NEAREST:
662 case GL_LINEAR:
663 break;
664
665 default:
666 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
667 return false;
668 }
669
670 return true;
671}
672
673template <typename ParamType>
674bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
675{
676 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
677 switch (ConvertToGLenum(params[0]))
678 {
679 case GL_NONE:
680 case GL_COMPARE_REF_TO_TEXTURE:
681 break;
682
683 default:
684 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
685 return false;
686 }
687
688 return true;
689}
690
691template <typename ParamType>
692bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
693{
694 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
695 switch (ConvertToGLenum(params[0]))
696 {
697 case GL_LEQUAL:
698 case GL_GEQUAL:
699 case GL_LESS:
700 case GL_GREATER:
701 case GL_EQUAL:
702 case GL_NOTEQUAL:
703 case GL_ALWAYS:
704 case GL_NEVER:
705 break;
706
707 default:
708 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
709 return false;
710 }
711
712 return true;
713}
714
715template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700716bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
717{
718 if (!context->getExtensions().textureSRGBDecode)
719 {
720 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
721 return false;
722 }
723
724 switch (ConvertToGLenum(params[0]))
725 {
726 case GL_DECODE_EXT:
727 case GL_SKIP_DECODE_EXT:
728 break;
729
730 default:
731 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
732 return false;
733 }
734
735 return true;
736}
737
738template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400739bool ValidateTexParameterBase(Context *context,
740 GLenum target,
741 GLenum pname,
742 GLsizei bufSize,
743 ParamType *params)
744{
745 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
746 {
747 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
748 return false;
749 }
750
751 if (context->getTargetTexture(target) == nullptr)
752 {
753 // Should only be possible for external textures
754 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
755 return false;
756 }
757
758 const GLsizei minBufSize = 1;
759 if (bufSize >= 0 && bufSize < minBufSize)
760 {
761 context->handleError(
762 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
763 return false;
764 }
765
766 switch (pname)
767 {
768 case GL_TEXTURE_WRAP_R:
769 case GL_TEXTURE_SWIZZLE_R:
770 case GL_TEXTURE_SWIZZLE_G:
771 case GL_TEXTURE_SWIZZLE_B:
772 case GL_TEXTURE_SWIZZLE_A:
773 case GL_TEXTURE_BASE_LEVEL:
774 case GL_TEXTURE_MAX_LEVEL:
775 case GL_TEXTURE_COMPARE_MODE:
776 case GL_TEXTURE_COMPARE_FUNC:
777 case GL_TEXTURE_MIN_LOD:
778 case GL_TEXTURE_MAX_LOD:
779 if (context->getClientMajorVersion() < 3)
780 {
781 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
782 return false;
783 }
784 if (target == GL_TEXTURE_EXTERNAL_OES &&
785 !context->getExtensions().eglImageExternalEssl3)
786 {
787 context->handleError(Error(GL_INVALID_ENUM,
788 "ES3 texture parameters are not available without "
789 "GL_OES_EGL_image_external_essl3."));
790 return false;
791 }
792 break;
793
794 default:
795 break;
796 }
797
798 switch (pname)
799 {
800 case GL_TEXTURE_WRAP_S:
801 case GL_TEXTURE_WRAP_T:
802 case GL_TEXTURE_WRAP_R:
803 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
804 {
805 return false;
806 }
807 break;
808
809 case GL_TEXTURE_MIN_FILTER:
810 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
811 {
812 return false;
813 }
814 break;
815
816 case GL_TEXTURE_MAG_FILTER:
817 if (!ValidateTextureMagFilterValue(context, params))
818 {
819 return false;
820 }
821 break;
822
823 case GL_TEXTURE_USAGE_ANGLE:
824 switch (ConvertToGLenum(params[0]))
825 {
826 case GL_NONE:
827 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
828 break;
829
830 default:
831 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
832 return false;
833 }
834 break;
835
836 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
837 if (!context->getExtensions().textureFilterAnisotropic)
838 {
839 context->handleError(
840 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
841 return false;
842 }
843
844 // we assume the parameter passed to this validation method is truncated, not rounded
845 if (params[0] < 1)
846 {
847 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
848 return false;
849 }
850 break;
851
852 case GL_TEXTURE_MIN_LOD:
853 case GL_TEXTURE_MAX_LOD:
854 // any value is permissible
855 break;
856
857 case GL_TEXTURE_COMPARE_MODE:
858 if (!ValidateTextureCompareModeValue(context, params))
859 {
860 return false;
861 }
862 break;
863
864 case GL_TEXTURE_COMPARE_FUNC:
865 if (!ValidateTextureCompareFuncValue(context, params))
866 {
867 return false;
868 }
869 break;
870
871 case GL_TEXTURE_SWIZZLE_R:
872 case GL_TEXTURE_SWIZZLE_G:
873 case GL_TEXTURE_SWIZZLE_B:
874 case GL_TEXTURE_SWIZZLE_A:
875 switch (ConvertToGLenum(params[0]))
876 {
877 case GL_RED:
878 case GL_GREEN:
879 case GL_BLUE:
880 case GL_ALPHA:
881 case GL_ZERO:
882 case GL_ONE:
883 break;
884
885 default:
886 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
887 return false;
888 }
889 break;
890
891 case GL_TEXTURE_BASE_LEVEL:
892 if (params[0] < 0)
893 {
894 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
895 return false;
896 }
897 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
898 {
899 context->handleError(
900 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
901 return false;
902 }
903 break;
904
905 case GL_TEXTURE_MAX_LEVEL:
906 if (params[0] < 0)
907 {
908 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
909 return false;
910 }
911 break;
912
Geoff Lang3b573612016-10-31 14:08:10 -0400913 case GL_DEPTH_STENCIL_TEXTURE_MODE:
914 if (context->getClientVersion() < Version(3, 1))
915 {
916 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
917 return false;
918 }
Geoff Lang9f090372016-12-02 10:20:43 -0500919 switch (ConvertToGLenum(params[0]))
920 {
921 case GL_DEPTH_COMPONENT:
922 case GL_STENCIL_INDEX:
923 break;
924
925 default:
926 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
927 return false;
928 }
Geoff Lang3b573612016-10-31 14:08:10 -0400929 break;
930
Geoff Lang81c6b572016-10-19 14:07:52 -0700931 case GL_TEXTURE_SRGB_DECODE_EXT:
932 if (!ValidateTextureSRGBDecodeValue(context, params))
933 {
934 return false;
935 }
936 break;
937
Geoff Langc1984ed2016-10-07 12:41:00 -0400938 default:
939 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
940 return false;
941 }
942
943 return true;
944}
945
946template <typename ParamType>
947bool ValidateSamplerParameterBase(Context *context,
948 GLuint sampler,
949 GLenum pname,
950 GLsizei bufSize,
951 ParamType *params)
952{
953 if (context->getClientMajorVersion() < 3)
954 {
955 context->handleError(
956 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
957 return false;
958 }
959
960 if (!context->isSampler(sampler))
961 {
962 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
963 return false;
964 }
965
966 const GLsizei minBufSize = 1;
967 if (bufSize >= 0 && bufSize < minBufSize)
968 {
969 context->handleError(
970 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
971 return false;
972 }
973
974 switch (pname)
975 {
976 case GL_TEXTURE_WRAP_S:
977 case GL_TEXTURE_WRAP_T:
978 case GL_TEXTURE_WRAP_R:
979 if (!ValidateTextureWrapModeValue(context, params, false))
980 {
981 return false;
982 }
983 break;
984
985 case GL_TEXTURE_MIN_FILTER:
986 if (!ValidateTextureMinFilterValue(context, params, false))
987 {
988 return false;
989 }
990 break;
991
992 case GL_TEXTURE_MAG_FILTER:
993 if (!ValidateTextureMagFilterValue(context, params))
994 {
995 return false;
996 }
997 break;
998
999 case GL_TEXTURE_MIN_LOD:
1000 case GL_TEXTURE_MAX_LOD:
1001 // any value is permissible
1002 break;
1003
1004 case GL_TEXTURE_COMPARE_MODE:
1005 if (!ValidateTextureCompareModeValue(context, params))
1006 {
1007 return false;
1008 }
1009 break;
1010
1011 case GL_TEXTURE_COMPARE_FUNC:
1012 if (!ValidateTextureCompareFuncValue(context, params))
1013 {
1014 return false;
1015 }
1016 break;
1017
Geoff Lang81c6b572016-10-19 14:07:52 -07001018 case GL_TEXTURE_SRGB_DECODE_EXT:
1019 if (!ValidateTextureSRGBDecodeValue(context, params))
1020 {
1021 return false;
1022 }
1023 break;
1024
Geoff Langc1984ed2016-10-07 12:41:00 -04001025 default:
1026 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1027 return false;
1028 }
1029
1030 return true;
1031}
1032
1033bool ValidateGetSamplerParameterBase(Context *context,
1034 GLuint sampler,
1035 GLenum pname,
1036 GLsizei *length)
1037{
1038 if (length)
1039 {
1040 *length = 0;
1041 }
1042
1043 if (context->getClientMajorVersion() < 3)
1044 {
1045 context->handleError(
1046 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1047 return false;
1048 }
1049
1050 if (!context->isSampler(sampler))
1051 {
1052 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
1053 return false;
1054 }
1055
1056 switch (pname)
1057 {
1058 case GL_TEXTURE_WRAP_S:
1059 case GL_TEXTURE_WRAP_T:
1060 case GL_TEXTURE_WRAP_R:
1061 case GL_TEXTURE_MIN_FILTER:
1062 case GL_TEXTURE_MAG_FILTER:
1063 case GL_TEXTURE_MIN_LOD:
1064 case GL_TEXTURE_MAX_LOD:
1065 case GL_TEXTURE_COMPARE_MODE:
1066 case GL_TEXTURE_COMPARE_FUNC:
1067 break;
1068
Geoff Lang81c6b572016-10-19 14:07:52 -07001069 case GL_TEXTURE_SRGB_DECODE_EXT:
1070 if (!context->getExtensions().textureSRGBDecode)
1071 {
1072 context->handleError(
1073 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
1074 return false;
1075 }
1076 break;
1077
Geoff Langc1984ed2016-10-07 12:41:00 -04001078 default:
1079 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1080 return false;
1081 }
1082
1083 if (length)
1084 {
1085 *length = 1;
1086 }
1087 return true;
1088}
1089
Geoff Lang0b031062016-10-13 14:30:04 -04001090bool ValidateGetVertexAttribBase(Context *context,
1091 GLuint index,
1092 GLenum pname,
1093 GLsizei *length,
1094 bool pointer,
1095 bool pureIntegerEntryPoint)
1096{
1097 if (length)
1098 {
1099 *length = 0;
1100 }
1101
1102 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1103 {
1104 context->handleError(
1105 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1106 return false;
1107 }
1108
1109 if (index >= context->getCaps().maxVertexAttributes)
1110 {
1111 context->handleError(Error(
1112 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1113 return false;
1114 }
1115
1116 if (pointer)
1117 {
1118 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1119 {
1120 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1121 return false;
1122 }
1123 }
1124 else
1125 {
1126 switch (pname)
1127 {
1128 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1129 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1130 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1131 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1132 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1133 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1134 case GL_CURRENT_VERTEX_ATTRIB:
1135 break;
1136
1137 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1138 static_assert(
1139 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1140 "ANGLE extension enums not equal to GL enums.");
1141 if (context->getClientMajorVersion() < 3 &&
1142 !context->getExtensions().instancedArrays)
1143 {
1144 context->handleError(Error(GL_INVALID_ENUM,
1145 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1146 "3.0 or GL_ANGLE_instanced_arrays."));
1147 return false;
1148 }
1149 break;
1150
1151 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1152 if (context->getClientMajorVersion() < 3)
1153 {
Shao80957d92017-02-20 21:25:59 +08001154 context->handleError(Error(
1155 GL_INVALID_ENUM, "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0."));
1156 return false;
1157 }
1158 break;
1159
1160 case GL_VERTEX_ATTRIB_BINDING:
1161 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
1162 if (context->getClientVersion() < ES_3_1)
1163 {
1164 context->handleError(
1165 Error(GL_INVALID_ENUM, "Vertex Attrib Bindings require OpenGL ES 3.1."));
Geoff Lang0b031062016-10-13 14:30:04 -04001166 return false;
1167 }
1168 break;
1169
1170 default:
1171 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1172 return false;
1173 }
1174 }
1175
1176 if (length)
1177 {
1178 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1179 {
1180 *length = 4;
1181 }
1182 else
1183 {
1184 *length = 1;
1185 }
1186 }
1187
1188 return true;
1189}
1190
Geoff Lang6899b872016-10-14 11:30:13 -04001191bool ValidateGetActiveUniformBlockivBase(Context *context,
1192 GLuint program,
1193 GLuint uniformBlockIndex,
1194 GLenum pname,
1195 GLsizei *length)
1196{
1197 if (length)
1198 {
1199 *length = 0;
1200 }
1201
1202 if (context->getClientMajorVersion() < 3)
1203 {
1204 context->handleError(
1205 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1206 return false;
1207 }
1208
1209 Program *programObject = GetValidProgram(context, program);
1210 if (!programObject)
1211 {
1212 return false;
1213 }
1214
1215 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1216 {
1217 context->handleError(
1218 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1219 return false;
1220 }
1221
1222 switch (pname)
1223 {
1224 case GL_UNIFORM_BLOCK_BINDING:
1225 case GL_UNIFORM_BLOCK_DATA_SIZE:
1226 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1227 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1228 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1229 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1230 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1231 break;
1232
1233 default:
1234 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1235 return false;
1236 }
1237
1238 if (length)
1239 {
1240 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1241 {
1242 const UniformBlock &uniformBlock =
1243 programObject->getUniformBlockByIndex(uniformBlockIndex);
1244 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1245 }
1246 else
1247 {
1248 *length = 1;
1249 }
1250 }
1251
1252 return true;
1253}
1254
Geoff Langebebe1c2016-10-14 12:01:31 -04001255bool ValidateGetBufferParameterBase(ValidationContext *context,
1256 GLenum target,
1257 GLenum pname,
1258 bool pointerVersion,
1259 GLsizei *numParams)
1260{
1261 if (numParams)
1262 {
1263 *numParams = 0;
1264 }
1265
1266 if (!ValidBufferTarget(context, target))
1267 {
1268 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1269 return false;
1270 }
1271
1272 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1273 if (!buffer)
1274 {
1275 // A null buffer means that "0" is bound to the requested buffer target
1276 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1277 return false;
1278 }
1279
1280 const Extensions &extensions = context->getExtensions();
1281
1282 switch (pname)
1283 {
1284 case GL_BUFFER_USAGE:
1285 case GL_BUFFER_SIZE:
1286 break;
1287
1288 case GL_BUFFER_ACCESS_OES:
1289 if (!extensions.mapBuffer)
1290 {
1291 context->handleError(
Jamie Madillcc6ac252017-01-25 12:57:21 -08001292 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001293 return false;
1294 }
1295 break;
1296
1297 case GL_BUFFER_MAPPED:
1298 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1299 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1300 !extensions.mapBufferRange)
1301 {
1302 context->handleError(Error(
1303 GL_INVALID_ENUM,
Jamie Madillcc6ac252017-01-25 12:57:21 -08001304 "pname requires OpenGL ES 3.0, GL_OES_mapbuffer or GL_EXT_map_buffer_range."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001305 return false;
1306 }
1307 break;
1308
1309 case GL_BUFFER_MAP_POINTER:
1310 if (!pointerVersion)
1311 {
1312 context->handleError(
1313 Error(GL_INVALID_ENUM,
1314 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1315 return false;
1316 }
1317 break;
1318
1319 case GL_BUFFER_ACCESS_FLAGS:
1320 case GL_BUFFER_MAP_OFFSET:
1321 case GL_BUFFER_MAP_LENGTH:
1322 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1323 {
1324 context->handleError(Error(
1325 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1326 return false;
1327 }
1328 break;
1329
1330 default:
1331 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1332 return false;
1333 }
1334
1335 // All buffer parameter queries return one value.
1336 if (numParams)
1337 {
1338 *numParams = 1;
1339 }
1340
1341 return true;
1342}
1343
Geoff Lang0a9661f2016-10-20 10:59:20 -07001344bool ValidateGetInternalFormativBase(Context *context,
1345 GLenum target,
1346 GLenum internalformat,
1347 GLenum pname,
1348 GLsizei bufSize,
1349 GLsizei *numParams)
1350{
1351 if (numParams)
1352 {
1353 *numParams = 0;
1354 }
1355
1356 if (context->getClientMajorVersion() < 3)
1357 {
1358 context->handleError(
1359 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1360 return false;
1361 }
1362
1363 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1364 if (!formatCaps.renderable)
1365 {
1366 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1367 return false;
1368 }
1369
1370 switch (target)
1371 {
1372 case GL_RENDERBUFFER:
1373 break;
1374
JiangYizhoubddc46b2016-12-09 09:50:51 +08001375 case GL_TEXTURE_2D_MULTISAMPLE:
1376 if (context->getClientVersion() < ES_3_1)
1377 {
1378 context->handleError(
1379 Error(GL_INVALID_OPERATION, "Texture target requires at least OpenGL ES 3.1."));
1380 return false;
1381 }
1382 break;
1383
Geoff Lang0a9661f2016-10-20 10:59:20 -07001384 default:
1385 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1386 return false;
1387 }
1388
1389 if (bufSize < 0)
1390 {
1391 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1392 return false;
1393 }
1394
1395 GLsizei maxWriteParams = 0;
1396 switch (pname)
1397 {
1398 case GL_NUM_SAMPLE_COUNTS:
1399 maxWriteParams = 1;
1400 break;
1401
1402 case GL_SAMPLES:
1403 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1404 break;
1405
1406 default:
1407 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1408 return false;
1409 }
1410
1411 if (numParams)
1412 {
1413 // glGetInternalFormativ will not overflow bufSize
1414 *numParams = std::min(bufSize, maxWriteParams);
1415 }
1416
1417 return true;
1418}
1419
Jamie Madillc1d770e2017-04-13 17:31:24 -04001420bool ValidateUniformCommonBase(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001421 gl::Program *program,
1422 GLint location,
1423 GLsizei count,
1424 const LinkedUniform **uniformOut)
1425{
1426 // TODO(Jiajia): Add image uniform check in future.
1427 if (count < 0)
1428 {
1429 context->handleError(Error(GL_INVALID_VALUE));
1430 return false;
1431 }
1432
1433 if (!program || !program->isLinked())
1434 {
1435 context->handleError(Error(GL_INVALID_OPERATION));
1436 return false;
1437 }
1438
1439 if (location == -1)
1440 {
1441 // Silently ignore the uniform command
1442 return false;
1443 }
1444
1445 const auto &uniformLocations = program->getUniformLocations();
1446 size_t castedLocation = static_cast<size_t>(location);
1447 if (castedLocation >= uniformLocations.size())
1448 {
1449 context->handleError(Error(GL_INVALID_OPERATION, "Invalid uniform location"));
1450 return false;
1451 }
1452
1453 const auto &uniformLocation = uniformLocations[castedLocation];
1454 if (uniformLocation.ignored)
1455 {
1456 // Silently ignore the uniform command
1457 return false;
1458 }
1459
1460 if (!uniformLocation.used)
1461 {
1462 context->handleError(Error(GL_INVALID_OPERATION));
1463 return false;
1464 }
1465
1466 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
1467
1468 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
1469 if (!uniform.isArray() && count > 1)
1470 {
1471 context->handleError(Error(GL_INVALID_OPERATION));
1472 return false;
1473 }
1474
1475 *uniformOut = &uniform;
1476 return true;
1477}
1478
Frank Henigman999b0fd2017-02-02 21:45:55 -05001479bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -05001480 GLenum uniformType,
1481 GLsizei count,
1482 const GLint *value)
1483{
1484 // Value type is GL_INT, because we only get here from glUniform1i{v}.
1485 // It is compatible with INT or BOOL.
1486 // Do these cheap tests first, for a little extra speed.
1487 if (GL_INT == uniformType || GL_BOOL == uniformType)
1488 {
1489 return true;
1490 }
1491
1492 if (IsSamplerType(uniformType))
1493 {
Frank Henigman999b0fd2017-02-02 21:45:55 -05001494 // Check that the values are in range.
1495 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
1496 for (GLsizei i = 0; i < count; ++i)
1497 {
1498 if (value[i] < 0 || value[i] >= max)
1499 {
1500 context->handleError(Error(GL_INVALID_VALUE, "sampler uniform value out of range"));
1501 return false;
1502 }
1503 }
Frank Henigmana98a6472017-02-02 21:38:32 -05001504 return true;
1505 }
1506
1507 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1508 return false;
1509}
1510
Jamie Madillc1d770e2017-04-13 17:31:24 -04001511bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001512{
1513 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -05001514 // Do the cheaper test first, for a little extra speed.
1515 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001516 {
1517 return true;
1518 }
1519
1520 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1521 return false;
1522}
1523
Jamie Madillc1d770e2017-04-13 17:31:24 -04001524bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001525{
1526 // Check that the value type is compatible with uniform type.
1527 if (valueType == uniformType)
1528 {
1529 return true;
1530 }
1531
1532 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1533 return false;
1534}
1535
Jamie Madillc1d770e2017-04-13 17:31:24 -04001536bool ValidateES2CopyTexImageParameters(ValidationContext *context,
1537 GLenum target,
1538 GLint level,
1539 GLenum internalformat,
1540 bool isSubImage,
1541 GLint xoffset,
1542 GLint yoffset,
1543 GLint x,
1544 GLint y,
1545 GLsizei width,
1546 GLsizei height,
1547 GLint border)
1548{
1549 if (!ValidTexture2DDestinationTarget(context, target))
1550 {
1551 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
1552 return false;
1553 }
1554
1555 if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
1556 {
1557 context->handleError(Error(GL_INVALID_VALUE, "Invalid texture dimensions."));
1558 return false;
1559 }
1560
1561 Format textureFormat = Format::Invalid();
1562 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
1563 xoffset, yoffset, 0, x, y, width, height, border,
1564 &textureFormat))
1565 {
1566 return false;
1567 }
1568
1569 const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Geoff Langca271392017-04-05 12:30:00 -04001570 GLenum colorbufferFormat =
1571 framebuffer->getReadColorbuffer()->getFormat().info->sizedInternalFormat;
Jamie Madillc1d770e2017-04-13 17:31:24 -04001572 const auto &formatInfo = *textureFormat.info;
1573
1574 // [OpenGL ES 2.0.24] table 3.9
1575 if (isSubImage)
1576 {
1577 switch (formatInfo.format)
1578 {
1579 case GL_ALPHA:
1580 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
1581 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES)
1582 {
1583 context->handleError(Error(GL_INVALID_OPERATION));
1584 return false;
1585 }
1586 break;
1587 case GL_LUMINANCE:
1588 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
1589 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
1590 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
1591 colorbufferFormat != GL_RGBA8_OES)
1592 {
1593 context->handleError(Error(GL_INVALID_OPERATION));
1594 return false;
1595 }
1596 break;
1597 case GL_RED_EXT:
1598 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
1599 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
1600 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
1601 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
1602 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
1603 colorbufferFormat != GL_RGBA32F)
1604 {
1605 context->handleError(Error(GL_INVALID_OPERATION));
1606 return false;
1607 }
1608 break;
1609 case GL_RG_EXT:
1610 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
1611 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
1612 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
1613 colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
1614 colorbufferFormat != GL_RGBA32F)
1615 {
1616 context->handleError(Error(GL_INVALID_OPERATION));
1617 return false;
1618 }
1619 break;
1620 case GL_RGB:
1621 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
1622 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
1623 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
1624 colorbufferFormat != GL_RGBA32F)
1625 {
1626 context->handleError(Error(GL_INVALID_OPERATION));
1627 return false;
1628 }
1629 break;
1630 case GL_LUMINANCE_ALPHA:
1631 case GL_RGBA:
1632 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
1633 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F)
1634 {
1635 context->handleError(Error(GL_INVALID_OPERATION));
1636 return false;
1637 }
1638 break;
1639 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1640 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1641 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1642 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1643 case GL_ETC1_RGB8_OES:
1644 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1645 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1646 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1647 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1648 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1649 context->handleError(Error(GL_INVALID_OPERATION));
1650 return false;
1651 case GL_DEPTH_COMPONENT:
1652 case GL_DEPTH_STENCIL_OES:
1653 context->handleError(Error(GL_INVALID_OPERATION));
1654 return false;
1655 default:
1656 context->handleError(Error(GL_INVALID_OPERATION));
1657 return false;
1658 }
1659
1660 if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
1661 {
1662 context->handleError(Error(GL_INVALID_OPERATION));
1663 return false;
1664 }
1665 }
1666 else
1667 {
1668 switch (internalformat)
1669 {
1670 case GL_ALPHA:
1671 if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
1672 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
1673 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
1674 {
1675 context->handleError(Error(GL_INVALID_OPERATION));
1676 return false;
1677 }
1678 break;
1679 case GL_LUMINANCE:
1680 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
1681 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
1682 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
1683 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
1684 colorbufferFormat != GL_BGR5_A1_ANGLEX)
1685 {
1686 context->handleError(Error(GL_INVALID_OPERATION));
1687 return false;
1688 }
1689 break;
1690 case GL_RED_EXT:
1691 if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
1692 colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
1693 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
1694 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
1695 colorbufferFormat != GL_BGR5_A1_ANGLEX)
1696 {
1697 context->handleError(Error(GL_INVALID_OPERATION));
1698 return false;
1699 }
1700 break;
1701 case GL_RG_EXT:
1702 if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
1703 colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
1704 colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
1705 colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
1706 {
1707 context->handleError(Error(GL_INVALID_OPERATION));
1708 return false;
1709 }
1710 break;
1711 case GL_RGB:
1712 if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
1713 colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
1714 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
1715 colorbufferFormat != GL_BGR5_A1_ANGLEX)
1716 {
1717 context->handleError(Error(GL_INVALID_OPERATION));
1718 return false;
1719 }
1720 break;
1721 case GL_LUMINANCE_ALPHA:
1722 case GL_RGBA:
1723 if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
1724 colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
1725 colorbufferFormat != GL_BGR5_A1_ANGLEX)
1726 {
1727 context->handleError(Error(GL_INVALID_OPERATION));
1728 return false;
1729 }
1730 break;
1731 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1732 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1733 if (context->getExtensions().textureCompressionDXT1)
1734 {
1735 context->handleError(Error(GL_INVALID_OPERATION));
1736 return false;
1737 }
1738 else
1739 {
1740 context->handleError(Error(GL_INVALID_ENUM));
1741 return false;
1742 }
1743 break;
1744 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1745 if (context->getExtensions().textureCompressionDXT3)
1746 {
1747 context->handleError(Error(GL_INVALID_OPERATION));
1748 return false;
1749 }
1750 else
1751 {
1752 context->handleError(Error(GL_INVALID_ENUM));
1753 return false;
1754 }
1755 break;
1756 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
1757 if (context->getExtensions().textureCompressionDXT5)
1758 {
1759 context->handleError(Error(GL_INVALID_OPERATION));
1760 return false;
1761 }
1762 else
1763 {
1764 context->handleError(Error(GL_INVALID_ENUM));
1765 return false;
1766 }
1767 break;
1768 case GL_ETC1_RGB8_OES:
1769 if (context->getExtensions().compressedETC1RGB8Texture)
1770 {
1771 context->handleError(Error(GL_INVALID_OPERATION));
1772 return false;
1773 }
1774 else
1775 {
1776 context->handleError(Error(GL_INVALID_ENUM));
1777 return false;
1778 }
1779 break;
1780 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
1781 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1782 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1783 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1784 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1785 if (context->getExtensions().lossyETCDecode)
1786 {
1787 context->handleError(Error(GL_INVALID_OPERATION,
1788 "ETC lossy decode formats can't be copied to."));
1789 return false;
1790 }
1791 else
1792 {
1793 context->handleError(Error(
1794 GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported."));
1795 return false;
1796 }
1797 break;
1798 case GL_DEPTH_COMPONENT:
1799 case GL_DEPTH_COMPONENT16:
1800 case GL_DEPTH_COMPONENT32_OES:
1801 case GL_DEPTH_STENCIL_OES:
1802 case GL_DEPTH24_STENCIL8_OES:
1803 if (context->getExtensions().depthTextures)
1804 {
1805 context->handleError(Error(GL_INVALID_OPERATION));
1806 return false;
1807 }
1808 else
1809 {
1810 context->handleError(Error(GL_INVALID_ENUM));
1811 return false;
1812 }
1813 default:
1814 context->handleError(Error(GL_INVALID_ENUM));
1815 return false;
1816 }
1817 }
1818
1819 // If width or height is zero, it is a no-op. Return false without setting an error.
1820 return (width > 0 && height > 0);
1821}
1822
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001823bool ValidateDrawElementsInstancedBase(ValidationContext *context,
Geoff Lang407d4e72017-04-12 14:54:11 -04001824 GLenum mode,
1825 GLsizei count,
1826 GLenum type,
1827 const GLvoid *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001828 GLsizei primcount)
Geoff Lang407d4e72017-04-12 14:54:11 -04001829{
1830 if (primcount < 0)
1831 {
1832 context->handleError(Error(GL_INVALID_VALUE, "primcount cannot be negative."));
1833 return false;
1834 }
1835
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001836 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
Geoff Lang407d4e72017-04-12 14:54:11 -04001837 {
1838 return false;
1839 }
1840
1841 // No-op zero primitive count
1842 return (primcount > 0);
1843}
1844
1845bool ValidateDrawArraysInstancedBase(Context *context,
1846 GLenum mode,
1847 GLint first,
1848 GLsizei count,
1849 GLsizei primcount)
1850{
1851 if (primcount < 0)
1852 {
1853 context->handleError(Error(GL_INVALID_VALUE, "primcount cannot be negative."));
1854 return false;
1855 }
1856
1857 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
1858 {
1859 return false;
1860 }
1861
1862 // No-op if zero primitive count
1863 return (primcount > 0);
1864}
1865
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001866bool ValidateDrawInstancedANGLEAndWebGL(ValidationContext *context)
Geoff Lang407d4e72017-04-12 14:54:11 -04001867{
1868 // Verify there is at least one active attribute with a divisor of zero
1869 const State &state = context->getGLState();
1870
1871 Program *program = state.getProgram();
1872
1873 const auto &attribs = state.getVertexArray()->getVertexAttributes();
1874 const auto &bindings = state.getVertexArray()->getVertexBindings();
1875 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
1876 {
1877 const VertexAttribute &attrib = attribs[attributeIndex];
1878 const VertexBinding &binding = bindings[attrib.bindingIndex];
1879 if (program->isAttribLocationActive(attributeIndex) && binding.divisor == 0)
1880 {
1881 return true;
1882 }
1883 }
1884
1885 context->handleError(
1886 Error(GL_INVALID_OPERATION, "At least one attribute must have a divisor of zero."));
1887 return false;
1888}
1889
Geoff Langf41a7152016-09-19 15:11:17 -04001890} // anonymous namespace
1891
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001892bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001893{
Jamie Madilld7460c72014-01-21 16:38:14 -05001894 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001895 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001896 case GL_TEXTURE_2D:
1897 case GL_TEXTURE_CUBE_MAP:
1898 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001899
He Yunchaoced53ae2016-11-29 15:00:51 +08001900 case GL_TEXTURE_3D:
1901 case GL_TEXTURE_2D_ARRAY:
1902 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001903
He Yunchaoced53ae2016-11-29 15:00:51 +08001904 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001905 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001906
He Yunchaoced53ae2016-11-29 15:00:51 +08001907 default:
1908 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001909 }
Jamie Madill35d15012013-10-07 10:46:37 -04001910}
1911
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001912bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1913{
1914 switch (target)
1915 {
1916 case GL_TEXTURE_2D:
1917 case GL_TEXTURE_CUBE_MAP:
1918 return true;
1919
1920 default:
1921 return false;
1922 }
1923}
1924
1925bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1926{
1927 switch (target)
1928 {
1929 case GL_TEXTURE_3D:
1930 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001931 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001932
1933 default:
1934 return false;
1935 }
1936}
1937
Ian Ewellbda75592016-04-18 17:25:54 -04001938// Most texture GL calls are not compatible with external textures, so we have a separate validation
1939// function for use in the GL calls that do
1940bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1941{
1942 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1943 (context->getExtensions().eglImageExternal ||
1944 context->getExtensions().eglStreamConsumerExternal);
1945}
1946
Shannon Woods4dfed832014-03-17 20:03:39 -04001947// This function differs from ValidTextureTarget in that the target must be
1948// usable as the destination of a 2D operation-- so a cube face is valid, but
1949// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001950// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001951bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001952{
1953 switch (target)
1954 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001955 case GL_TEXTURE_2D:
1956 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1957 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1958 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1959 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1960 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1961 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1962 return true;
1963 default:
1964 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001965 }
1966}
1967
1968bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1969{
1970 switch (target)
1971 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001972 case GL_TEXTURE_3D:
1973 case GL_TEXTURE_2D_ARRAY:
1974 return true;
1975 default:
1976 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001977 }
1978}
1979
He Yunchao11b038b2016-11-22 21:24:04 +08001980bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1981{
1982 switch (target)
1983 {
1984 case GL_TEXTURE_2D:
1985 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1986 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1987 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1988 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1989 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1990 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1991 case GL_TEXTURE_3D:
1992 case GL_TEXTURE_2D_ARRAY:
1993 case GL_TEXTURE_2D_MULTISAMPLE:
1994 return true;
1995 default:
1996 return false;
1997 }
1998}
1999
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002000bool ValidFramebufferTarget(GLenum target)
2001{
He Yunchaoced53ae2016-11-29 15:00:51 +08002002 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
2003 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04002004 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002005
2006 switch (target)
2007 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002008 case GL_FRAMEBUFFER:
2009 return true;
2010 case GL_READ_FRAMEBUFFER:
2011 return true;
2012 case GL_DRAW_FRAMEBUFFER:
2013 return true;
2014 default:
2015 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002016 }
2017}
2018
Jamie Madill29639852016-09-02 15:00:09 -04002019bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05002020{
2021 switch (target)
2022 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002023 case GL_ARRAY_BUFFER:
2024 case GL_ELEMENT_ARRAY_BUFFER:
2025 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05002026
He Yunchaoced53ae2016-11-29 15:00:51 +08002027 case GL_PIXEL_PACK_BUFFER:
2028 case GL_PIXEL_UNPACK_BUFFER:
2029 return (context->getExtensions().pixelBufferObject ||
2030 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04002031
He Yunchaoced53ae2016-11-29 15:00:51 +08002032 case GL_COPY_READ_BUFFER:
2033 case GL_COPY_WRITE_BUFFER:
2034 case GL_TRANSFORM_FEEDBACK_BUFFER:
2035 case GL_UNIFORM_BUFFER:
2036 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05002037
He Yunchaoced53ae2016-11-29 15:00:51 +08002038 case GL_ATOMIC_COUNTER_BUFFER:
2039 case GL_SHADER_STORAGE_BUFFER:
2040 case GL_DRAW_INDIRECT_BUFFER:
2041 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08002042 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04002043
He Yunchaoced53ae2016-11-29 15:00:51 +08002044 default:
2045 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05002046 }
2047}
2048
Jamie Madillc29968b2016-01-20 11:17:23 -05002049bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04002050{
Jamie Madillc29968b2016-01-20 11:17:23 -05002051 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04002052 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04002053 switch (target)
2054 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002055 case GL_TEXTURE_2D:
2056 maxDimension = caps.max2DTextureSize;
2057 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002058 case GL_TEXTURE_CUBE_MAP:
2059 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2060 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2061 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2062 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2063 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2064 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2065 maxDimension = caps.maxCubeMapTextureSize;
2066 break;
2067 case GL_TEXTURE_3D:
2068 maxDimension = caps.max3DTextureSize;
2069 break;
2070 case GL_TEXTURE_2D_ARRAY:
2071 maxDimension = caps.max2DTextureSize;
2072 break;
He Yunchao11b038b2016-11-22 21:24:04 +08002073 case GL_TEXTURE_2D_MULTISAMPLE:
2074 maxDimension = caps.max2DTextureSize;
2075 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002076 default:
2077 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04002078 }
2079
Cooper Partin4d61f7e2015-08-12 10:56:50 -07002080 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04002081}
2082
Geoff Langcc507aa2016-12-12 10:09:52 -05002083bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07002084 GLenum target,
2085 GLint level,
2086 GLsizei width,
2087 GLsizei height,
2088 GLsizei depth,
2089 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04002090{
2091 if (level < 0 || width < 0 || height < 0 || depth < 0)
2092 {
2093 return false;
2094 }
2095
Austin Kinross08528e12015-10-07 16:24:40 -07002096 // TexSubImage parameters can be NPOT without textureNPOT extension,
2097 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05002098 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05002099 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05002100 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04002101 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04002102 {
2103 return false;
2104 }
2105
2106 if (!ValidMipLevel(context, target, level))
2107 {
2108 return false;
2109 }
2110
2111 return true;
2112}
2113
Geoff Lang0d8b7242015-09-09 14:56:53 -04002114bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
2115{
2116 // List of compressed format that require that the texture size is smaller than or a multiple of
2117 // the compressed block size.
2118 switch (internalFormat)
2119 {
2120 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
2121 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
2122 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
2123 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08002124 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08002125 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
2126 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
2127 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
2128 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
2129 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
2130 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04002131 return true;
2132
2133 default:
2134 return false;
2135 }
2136}
2137
Geoff Lang966c9402017-04-18 12:38:27 -04002138bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
2139{
2140 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
2141 (size % blockSize == 0);
2142}
2143
Jamie Madillc29968b2016-01-20 11:17:23 -05002144bool ValidCompressedImageSize(const ValidationContext *context,
2145 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -04002146 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -05002147 GLsizei width,
2148 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04002149{
Geoff Langca271392017-04-05 12:30:00 -04002150 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04002151 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04002152 {
2153 return false;
2154 }
2155
Geoff Lang966c9402017-04-18 12:38:27 -04002156 if (width < 0 || height < 0)
2157 {
2158 return false;
2159 }
2160
2161 if (CompressedTextureFormatRequiresExactSize(internalFormat))
2162 {
2163 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
2164 // block size for level 0 but WebGL disallows this.
2165 bool smallerThanBlockSizeAllowed =
2166 level > 0 || !context->getExtensions().webglCompatibility;
2167
2168 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
2169 smallerThanBlockSizeAllowed) ||
2170 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
2171 smallerThanBlockSizeAllowed))
2172 {
2173 return false;
2174 }
2175 }
2176
2177 return true;
2178}
2179
2180bool ValidCompressedSubImageSize(const ValidationContext *context,
2181 GLenum internalFormat,
2182 GLint xoffset,
2183 GLint yoffset,
2184 GLsizei width,
2185 GLsizei height,
2186 size_t textureWidth,
2187 size_t textureHeight)
2188{
2189 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
2190 if (!formatInfo.compressed)
2191 {
2192 return false;
2193 }
2194
Geoff Lang44ff5a72017-02-03 15:15:43 -05002195 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04002196 {
2197 return false;
2198 }
2199
Geoff Lang0d8b7242015-09-09 14:56:53 -04002200 if (CompressedTextureFormatRequiresExactSize(internalFormat))
2201 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05002202 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -04002203 yoffset % formatInfo.compressedBlockHeight != 0)
2204 {
2205 return false;
2206 }
2207
2208 // Allowed to either have data that is a multiple of block size or is smaller than the block
2209 // size but fills the entire mip
2210 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
2211 static_cast<size_t>(width) == textureWidth &&
2212 static_cast<size_t>(height) == textureHeight;
2213 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
2214 (height % formatInfo.compressedBlockHeight) == 0;
2215 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -04002216 {
2217 return false;
2218 }
2219 }
2220
Geoff Langd4f180b2013-09-24 13:57:44 -04002221 return true;
2222}
2223
Geoff Langff5b2d52016-09-07 11:32:23 -04002224bool ValidImageDataSize(ValidationContext *context,
2225 GLenum textureTarget,
2226 GLsizei width,
2227 GLsizei height,
2228 GLsizei depth,
2229 GLenum internalFormat,
2230 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002231 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04002232 GLsizei imageSize)
2233{
2234 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
2235 if (pixelUnpackBuffer == nullptr && imageSize < 0)
2236 {
2237 // Checks are not required
2238 return true;
2239 }
2240
2241 // ...the data would be unpacked from the buffer object such that the memory reads required
2242 // would exceed the data store size.
Geoff Langca271392017-04-05 12:30:00 -04002243 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
Geoff Langff5b2d52016-09-07 11:32:23 -04002244 const gl::Extents size(width, height, depth);
2245 const auto &unpack = context->getGLState().getUnpackState();
2246
2247 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
2248 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
2249 if (endByteOrErr.isError())
2250 {
2251 context->handleError(endByteOrErr.getError());
2252 return false;
2253 }
2254
2255 GLuint endByte = endByteOrErr.getResult();
2256
2257 if (pixelUnpackBuffer)
2258 {
2259 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
2260 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
2261 checkedEndByte += checkedOffset;
2262
2263 if (!checkedEndByte.IsValid() ||
2264 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
2265 {
2266 // Overflow past the end of the buffer
2267 context->handleError(Error(GL_INVALID_OPERATION));
2268 return false;
2269 }
2270 }
2271 else
2272 {
2273 ASSERT(imageSize >= 0);
2274 if (pixels == nullptr && imageSize != 0)
2275 {
2276 context->handleError(
2277 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04002278 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04002279 }
2280
Geoff Lang3feb3ff2016-10-26 10:57:45 -04002281 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04002282 {
2283 context->handleError(
2284 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
2285 return false;
2286 }
2287 }
2288
2289 return true;
2290}
2291
Geoff Lang37dde692014-01-31 16:34:54 -05002292bool ValidQueryType(const Context *context, GLenum queryType)
2293{
He Yunchaoced53ae2016-11-29 15:00:51 +08002294 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
2295 "GL extension enums not equal.");
2296 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2297 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05002298
2299 switch (queryType)
2300 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002301 case GL_ANY_SAMPLES_PASSED:
2302 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
2303 return true;
2304 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
2305 return (context->getClientMajorVersion() >= 3);
2306 case GL_TIME_ELAPSED_EXT:
2307 return context->getExtensions().disjointTimerQuery;
2308 case GL_COMMANDS_COMPLETED_CHROMIUM:
2309 return context->getExtensions().syncQuery;
2310 default:
2311 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05002312 }
2313}
2314
Geoff Lang2d62ab72017-03-23 16:54:40 -04002315bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
2316 GLenum type,
2317 GLboolean normalized,
2318 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002319 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04002320 bool pureInteger)
2321{
2322 ASSERT(context->getExtensions().webglCompatibility);
2323
2324 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
2325 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
2326 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
2327 // parameter exceeds 255.
2328 constexpr GLsizei kMaxWebGLStride = 255;
2329 if (stride > kMaxWebGLStride)
2330 {
2331 context->handleError(
2332 Error(GL_INVALID_VALUE, "Stride is over the maximum stride allowed by WebGL."));
2333 return false;
2334 }
2335
2336 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
2337 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
2338 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
2339 // or an INVALID_OPERATION error is generated.
2340 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
2341 size_t typeSize = GetVertexFormatTypeSize(internalType);
2342
2343 ASSERT(isPow2(typeSize) && typeSize > 0);
2344 size_t sizeMask = (typeSize - 1);
2345 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
2346 {
2347 context->handleError(
2348 Error(GL_INVALID_OPERATION, "Offset is not a multiple of the type size."));
2349 return false;
2350 }
2351
2352 if ((stride & sizeMask) != 0)
2353 {
2354 context->handleError(
2355 Error(GL_INVALID_OPERATION, "Stride is not a multiple of the type size."));
2356 return false;
2357 }
2358
2359 return true;
2360}
2361
Jamie Madillef300b12016-10-07 15:12:09 -04002362Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05002363{
He Yunchaoced53ae2016-11-29 15:00:51 +08002364 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
2365 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
2366 // or program object and INVALID_OPERATION if the provided name identifies an object
2367 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05002368
Dian Xiang769769a2015-09-09 15:20:08 -07002369 Program *validProgram = context->getProgram(id);
2370
2371 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05002372 {
Dian Xiang769769a2015-09-09 15:20:08 -07002373 if (context->getShader(id))
2374 {
Jamie Madill437fa652016-05-03 15:13:24 -04002375 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07002376 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
2377 }
2378 else
2379 {
Jamie Madill437fa652016-05-03 15:13:24 -04002380 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07002381 }
Geoff Lang48dcae72014-02-05 16:28:24 -05002382 }
Dian Xiang769769a2015-09-09 15:20:08 -07002383
2384 return validProgram;
2385}
2386
Jamie Madillef300b12016-10-07 15:12:09 -04002387Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07002388{
2389 // See ValidProgram for spec details.
2390
2391 Shader *validShader = context->getShader(id);
2392
2393 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05002394 {
Dian Xiang769769a2015-09-09 15:20:08 -07002395 if (context->getProgram(id))
2396 {
Jamie Madill437fa652016-05-03 15:13:24 -04002397 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07002398 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
2399 }
2400 else
2401 {
Jamie Madill437fa652016-05-03 15:13:24 -04002402 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07002403 }
Geoff Lang48dcae72014-02-05 16:28:24 -05002404 }
Dian Xiang769769a2015-09-09 15:20:08 -07002405
2406 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05002407}
2408
Geoff Langb1196682014-07-23 13:47:29 -04002409bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04002410{
2411 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
2412 {
2413 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
2414
Geoff Langaae65a42014-05-26 12:43:44 -04002415 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04002416 {
Jamie Madill437fa652016-05-03 15:13:24 -04002417 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002418 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04002419 }
2420 }
2421 else
2422 {
2423 switch (attachment)
2424 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002425 case GL_DEPTH_ATTACHMENT:
2426 case GL_STENCIL_ATTACHMENT:
2427 break;
Jamie Madillb4472272014-07-03 10:38:55 -04002428
He Yunchaoced53ae2016-11-29 15:00:51 +08002429 case GL_DEPTH_STENCIL_ATTACHMENT:
2430 if (!context->getExtensions().webglCompatibility &&
2431 context->getClientMajorVersion() < 3)
2432 {
2433 context->handleError(Error(GL_INVALID_ENUM));
2434 return false;
2435 }
2436 break;
Jamie Madillb4472272014-07-03 10:38:55 -04002437
He Yunchaoced53ae2016-11-29 15:00:51 +08002438 default:
2439 context->handleError(Error(GL_INVALID_ENUM));
2440 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04002441 }
2442 }
2443
2444 return true;
2445}
2446
Jamie Madille8fb6402017-02-14 17:56:40 -05002447bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08002448 GLenum target,
2449 GLsizei samples,
2450 GLenum internalformat,
2451 GLsizei width,
2452 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002453{
2454 switch (target)
2455 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002456 case GL_RENDERBUFFER:
2457 break;
2458 default:
2459 context->handleError(Error(GL_INVALID_ENUM));
2460 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002461 }
2462
2463 if (width < 0 || height < 0 || samples < 0)
2464 {
Jamie Madill437fa652016-05-03 15:13:24 -04002465 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002466 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002467 }
2468
Jamie Madill4e0e6f82017-02-17 11:06:03 -05002469 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
2470 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
2471
2472 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04002473 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002474 {
Jamie Madill437fa652016-05-03 15:13:24 -04002475 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002476 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002477 }
2478
2479 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
2480 // 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 -08002481 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04002482 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
2483 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002484 {
Jamie Madill437fa652016-05-03 15:13:24 -04002485 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002486 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002487 }
2488
Geoff Langaae65a42014-05-26 12:43:44 -04002489 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002490 {
Jamie Madill437fa652016-05-03 15:13:24 -04002491 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002492 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002493 }
2494
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002495 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002496 if (handle == 0)
2497 {
Jamie Madill437fa652016-05-03 15:13:24 -04002498 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002499 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002500 }
2501
2502 return true;
2503}
2504
He Yunchaoced53ae2016-11-29 15:00:51 +08002505bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
2506 GLenum target,
2507 GLenum attachment,
2508 GLenum renderbuffertarget,
2509 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002510{
Shannon Woods1da3cf62014-06-27 15:32:23 -04002511 if (!ValidFramebufferTarget(target))
2512 {
Jamie Madill437fa652016-05-03 15:13:24 -04002513 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002514 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04002515 }
2516
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002517 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002518
Jamie Madill84115c92015-04-23 15:00:07 -04002519 ASSERT(framebuffer);
2520 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002521 {
Jamie Madill437fa652016-05-03 15:13:24 -04002522 context->handleError(
2523 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002524 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002525 }
2526
Jamie Madillb4472272014-07-03 10:38:55 -04002527 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002528 {
Jamie Madillb4472272014-07-03 10:38:55 -04002529 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002530 }
2531
Jamie Madillab9d82c2014-01-21 16:38:14 -05002532 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2533 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2534 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2535 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2536 if (renderbuffer != 0)
2537 {
2538 if (!context->getRenderbuffer(renderbuffer))
2539 {
Jamie Madill437fa652016-05-03 15:13:24 -04002540 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002541 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05002542 }
2543 }
2544
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002545 return true;
2546}
2547
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002548bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002549 GLint srcX0,
2550 GLint srcY0,
2551 GLint srcX1,
2552 GLint srcY1,
2553 GLint dstX0,
2554 GLint dstY0,
2555 GLint dstX1,
2556 GLint dstY1,
2557 GLbitfield mask,
2558 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002559{
2560 switch (filter)
2561 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002562 case GL_NEAREST:
2563 break;
2564 case GL_LINEAR:
2565 break;
2566 default:
2567 context->handleError(Error(GL_INVALID_ENUM));
2568 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002569 }
2570
2571 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
2572 {
Jamie Madill437fa652016-05-03 15:13:24 -04002573 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002574 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002575 }
2576
2577 if (mask == 0)
2578 {
2579 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
2580 // buffers are copied.
2581 return false;
2582 }
2583
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002584 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
2585 // color buffer, leaving only nearest being unfiltered from above
2586 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
2587 {
Jamie Madill437fa652016-05-03 15:13:24 -04002588 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002589 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002590 }
2591
Jamie Madill51f40ec2016-06-15 14:06:00 -04002592 const auto &glState = context->getGLState();
2593 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2594 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05002595
2596 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002597 {
Jamie Madill437fa652016-05-03 15:13:24 -04002598 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002599 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002600 }
2601
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002602 if (readFramebuffer->id() == drawFramebuffer->id())
2603 {
2604 context->handleError(Error(GL_INVALID_OPERATION));
2605 return false;
2606 }
2607
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002608 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002609 {
Jamie Madill437fa652016-05-03 15:13:24 -04002610 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002611 return false;
2612 }
2613
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002614 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002615 {
Jamie Madill437fa652016-05-03 15:13:24 -04002616 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002617 return false;
2618 }
2619
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002620 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002621 {
Jamie Madill437fa652016-05-03 15:13:24 -04002622 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002623 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002624 }
2625
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002626 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2627
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002628 if (mask & GL_COLOR_BUFFER_BIT)
2629 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002630 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002631 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002632
He Yunchao66a41a22016-12-15 16:45:05 +08002633 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002634 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002635 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002636
Geoff Langa15472a2015-08-11 11:48:03 -04002637 for (size_t drawbufferIdx = 0;
2638 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002639 {
Geoff Langa15472a2015-08-11 11:48:03 -04002640 const FramebufferAttachment *attachment =
2641 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2642 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002643 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002644 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002645
Geoff Langb2f3d052013-08-13 12:49:27 -04002646 // The GL ES 3.0.2 spec (pg 193) states that:
2647 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002648 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2649 // as well
2650 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2651 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002652 // Changes with EXT_color_buffer_float:
2653 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002654 GLenum readComponentType = readFormat.info->componentType;
2655 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002656 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002657 readComponentType == GL_SIGNED_NORMALIZED);
2658 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2659 drawComponentType == GL_SIGNED_NORMALIZED);
2660
2661 if (extensions.colorBufferFloat)
2662 {
2663 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2664 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2665
2666 if (readFixedOrFloat != drawFixedOrFloat)
2667 {
Jamie Madill437fa652016-05-03 15:13:24 -04002668 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002669 "If the read buffer contains fixed-point or "
2670 "floating-point values, the draw buffer "
2671 "must as well."));
2672 return false;
2673 }
2674 }
2675 else if (readFixedPoint != drawFixedPoint)
2676 {
Jamie Madill437fa652016-05-03 15:13:24 -04002677 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002678 "If the read buffer contains fixed-point "
2679 "values, the draw buffer must as well."));
2680 return false;
2681 }
2682
2683 if (readComponentType == GL_UNSIGNED_INT &&
2684 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002685 {
Jamie Madill437fa652016-05-03 15:13:24 -04002686 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002687 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002688 }
2689
Jamie Madill6163c752015-12-07 16:32:59 -05002690 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002691 {
Jamie Madill437fa652016-05-03 15:13:24 -04002692 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002693 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002694 }
2695
Jamie Madilla3944d42016-07-22 22:13:26 -04002696 if (readColorBuffer->getSamples() > 0 &&
2697 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002698 {
Jamie Madill437fa652016-05-03 15:13:24 -04002699 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002700 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002701 }
Geoff Lange4915782017-04-12 15:19:07 -04002702
2703 if (context->getExtensions().webglCompatibility &&
2704 *readColorBuffer == *attachment)
2705 {
2706 context->handleError(
2707 Error(GL_INVALID_OPERATION,
2708 "Read and write color attachments cannot be the same image."));
2709 return false;
2710 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002711 }
2712 }
2713
Jamie Madilla3944d42016-07-22 22:13:26 -04002714 if ((readFormat.info->componentType == GL_INT ||
2715 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2716 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002717 {
Jamie Madill437fa652016-05-03 15:13:24 -04002718 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002719 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002720 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002721 }
He Yunchao66a41a22016-12-15 16:45:05 +08002722 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2723 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2724 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2725 // situation is an application error that would lead to a crash in ANGLE.
2726 else if (drawFramebuffer->hasEnabledDrawBuffer())
2727 {
2728 context->handleError(Error(
2729 GL_INVALID_OPERATION,
2730 "Attempt to read from a missing color attachment of a complete framebuffer."));
2731 return false;
2732 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002733 }
2734
He Yunchaoced53ae2016-11-29 15:00:51 +08002735 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002736 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2737 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002738 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002739 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002740 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002741 const gl::FramebufferAttachment *readBuffer =
2742 readFramebuffer->getAttachment(attachments[i]);
2743 const gl::FramebufferAttachment *drawBuffer =
2744 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002745
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002746 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002747 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002748 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002749 {
Jamie Madill437fa652016-05-03 15:13:24 -04002750 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002751 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002752 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002753
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002754 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002755 {
Jamie Madill437fa652016-05-03 15:13:24 -04002756 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002757 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002758 }
Geoff Lange4915782017-04-12 15:19:07 -04002759
2760 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
2761 {
2762 context->handleError(Error(
2763 GL_INVALID_OPERATION,
2764 "Read and write depth stencil attachments cannot be the same image."));
2765 return false;
2766 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002767 }
He Yunchao66a41a22016-12-15 16:45:05 +08002768 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2769 else if (drawBuffer)
2770 {
2771 context->handleError(Error(GL_INVALID_OPERATION,
2772 "Attempt to read from a missing depth/stencil "
2773 "attachment of a complete framebuffer."));
2774 return false;
2775 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002776 }
2777 }
2778
2779 return true;
2780}
2781
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002782bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002783 GLint x,
2784 GLint y,
2785 GLsizei width,
2786 GLsizei height,
2787 GLenum format,
2788 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002789 void *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002790{
Geoff Lange93daba2017-03-30 13:54:40 -04002791 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
2792 nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04002793}
2794
2795bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2796 GLint x,
2797 GLint y,
2798 GLsizei width,
2799 GLsizei height,
2800 GLenum format,
2801 GLenum type,
2802 GLsizei bufSize,
2803 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04002804 GLsizei *columns,
2805 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04002806 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04002807{
2808 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002809 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002810 return false;
2811 }
2812
Geoff Lang62fce5b2016-09-30 10:46:35 -04002813 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04002814 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002815 {
Geoff Langb1196682014-07-23 13:47:29 -04002816 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002817 }
2818
Geoff Lang62fce5b2016-09-30 10:46:35 -04002819 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002820 {
Geoff Langb1196682014-07-23 13:47:29 -04002821 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002822 }
2823
Jamie Madillc29968b2016-01-20 11:17:23 -05002824 return true;
2825}
2826
2827bool ValidateReadnPixelsEXT(Context *context,
2828 GLint x,
2829 GLint y,
2830 GLsizei width,
2831 GLsizei height,
2832 GLenum format,
2833 GLenum type,
2834 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002835 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05002836{
2837 if (bufSize < 0)
2838 {
Jamie Madill437fa652016-05-03 15:13:24 -04002839 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002840 return false;
2841 }
2842
Geoff Lang62fce5b2016-09-30 10:46:35 -04002843 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04002844 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04002845}
Jamie Madill26e91952014-03-05 15:01:27 -05002846
Geoff Lang62fce5b2016-09-30 10:46:35 -04002847bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2848 GLint x,
2849 GLint y,
2850 GLsizei width,
2851 GLsizei height,
2852 GLenum format,
2853 GLenum type,
2854 GLsizei bufSize,
2855 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04002856 GLsizei *columns,
2857 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04002858 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04002859{
2860 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002861 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002862 return false;
2863 }
2864
Geoff Lange93daba2017-03-30 13:54:40 -04002865 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2866 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002867 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002868 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002869 }
2870
Geoff Lang62fce5b2016-09-30 10:46:35 -04002871 if (!ValidateRobustBufferSize(context, bufSize, *length))
2872 {
2873 return false;
2874 }
2875
2876 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002877}
2878
Olli Etuaho41997e72016-03-10 13:38:39 +02002879bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002880{
2881 if (!context->getExtensions().occlusionQueryBoolean &&
2882 !context->getExtensions().disjointTimerQuery)
2883 {
Jamie Madill437fa652016-05-03 15:13:24 -04002884 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002885 return false;
2886 }
2887
Olli Etuaho41997e72016-03-10 13:38:39 +02002888 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002889}
2890
Olli Etuaho41997e72016-03-10 13:38:39 +02002891bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002892{
2893 if (!context->getExtensions().occlusionQueryBoolean &&
2894 !context->getExtensions().disjointTimerQuery)
2895 {
Jamie Madill437fa652016-05-03 15:13:24 -04002896 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002897 return false;
2898 }
2899
Olli Etuaho41997e72016-03-10 13:38:39 +02002900 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002901}
2902
2903bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002904{
2905 if (!ValidQueryType(context, target))
2906 {
Jamie Madill437fa652016-05-03 15:13:24 -04002907 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002908 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002909 }
2910
2911 if (id == 0)
2912 {
Jamie Madill437fa652016-05-03 15:13:24 -04002913 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002914 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002915 }
2916
2917 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2918 // of zero, if the active query object name for <target> is non-zero (for the
2919 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2920 // the active query for either target is non-zero), if <id> is the name of an
2921 // existing query object whose type does not match <target>, or if <id> is the
2922 // active query object name for any query type, the error INVALID_OPERATION is
2923 // generated.
2924
2925 // Ensure no other queries are active
2926 // NOTE: If other queries than occlusion are supported, we will need to check
2927 // separately that:
2928 // a) The query ID passed is not the current active query for any target/type
2929 // b) There are no active queries for the requested target (and in the case
2930 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2931 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002932
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002933 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002934 {
Jamie Madill437fa652016-05-03 15:13:24 -04002935 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002936 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002937 }
2938
2939 Query *queryObject = context->getQuery(id, true, target);
2940
2941 // check that name was obtained with glGenQueries
2942 if (!queryObject)
2943 {
Jamie Madill437fa652016-05-03 15:13:24 -04002944 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002945 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002946 }
2947
2948 // check for type mismatch
2949 if (queryObject->getType() != target)
2950 {
Jamie Madill437fa652016-05-03 15:13:24 -04002951 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002952 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002953 }
2954
2955 return true;
2956}
2957
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002958bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2959{
2960 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002961 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002962 {
Jamie Madill437fa652016-05-03 15:13:24 -04002963 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002964 return false;
2965 }
2966
2967 return ValidateBeginQueryBase(context, target, id);
2968}
2969
2970bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002971{
2972 if (!ValidQueryType(context, target))
2973 {
Jamie Madill437fa652016-05-03 15:13:24 -04002974 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002975 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002976 }
2977
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002978 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002979
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002980 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002981 {
Jamie Madill437fa652016-05-03 15:13:24 -04002982 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002983 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002984 }
2985
Jamie Madill45c785d2014-05-13 14:09:34 -04002986 return true;
2987}
2988
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002989bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2990{
2991 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002992 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002993 {
Jamie Madill437fa652016-05-03 15:13:24 -04002994 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002995 return false;
2996 }
2997
2998 return ValidateEndQueryBase(context, target);
2999}
3000
3001bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
3002{
3003 if (!context->getExtensions().disjointTimerQuery)
3004 {
Jamie Madill437fa652016-05-03 15:13:24 -04003005 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003006 return false;
3007 }
3008
3009 if (target != GL_TIMESTAMP_EXT)
3010 {
Jamie Madill437fa652016-05-03 15:13:24 -04003011 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003012 return false;
3013 }
3014
3015 Query *queryObject = context->getQuery(id, true, target);
3016 if (queryObject == nullptr)
3017 {
Jamie Madill437fa652016-05-03 15:13:24 -04003018 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003019 return false;
3020 }
3021
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003022 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003023 {
Jamie Madill437fa652016-05-03 15:13:24 -04003024 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003025 return false;
3026 }
3027
3028 return true;
3029}
3030
Geoff Lang2186c382016-10-14 10:54:54 -04003031bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003032{
Geoff Lang2186c382016-10-14 10:54:54 -04003033 if (numParams)
3034 {
3035 *numParams = 0;
3036 }
3037
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003038 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
3039 {
Jamie Madill437fa652016-05-03 15:13:24 -04003040 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003041 return false;
3042 }
3043
3044 switch (pname)
3045 {
3046 case GL_CURRENT_QUERY_EXT:
3047 if (target == GL_TIMESTAMP_EXT)
3048 {
Jamie Madill437fa652016-05-03 15:13:24 -04003049 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003050 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
3051 return false;
3052 }
3053 break;
3054 case GL_QUERY_COUNTER_BITS_EXT:
3055 if (!context->getExtensions().disjointTimerQuery ||
3056 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
3057 {
Jamie Madill437fa652016-05-03 15:13:24 -04003058 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003059 return false;
3060 }
3061 break;
3062 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003063 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003064 return false;
3065 }
3066
Geoff Lang2186c382016-10-14 10:54:54 -04003067 if (numParams)
3068 {
3069 // All queries return only one value
3070 *numParams = 1;
3071 }
3072
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003073 return true;
3074}
3075
3076bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
3077{
3078 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04003079 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003080 {
Jamie Madill437fa652016-05-03 15:13:24 -04003081 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003082 return false;
3083 }
3084
Geoff Lang2186c382016-10-14 10:54:54 -04003085 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003086}
3087
Geoff Lang2186c382016-10-14 10:54:54 -04003088bool ValidateGetQueryivRobustANGLE(Context *context,
3089 GLenum target,
3090 GLenum pname,
3091 GLsizei bufSize,
3092 GLsizei *length,
3093 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003094{
Geoff Lang2186c382016-10-14 10:54:54 -04003095 if (!ValidateRobustEntryPoint(context, bufSize))
3096 {
3097 return false;
3098 }
3099
3100 if (!ValidateGetQueryivBase(context, target, pname, length))
3101 {
3102 return false;
3103 }
3104
3105 if (!ValidateRobustBufferSize(context, bufSize, *length))
3106 {
3107 return false;
3108 }
3109
3110 return true;
3111}
3112
3113bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
3114{
3115 if (numParams)
3116 {
3117 *numParams = 0;
3118 }
3119
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003120 Query *queryObject = context->getQuery(id, false, GL_NONE);
3121
3122 if (!queryObject)
3123 {
Jamie Madill437fa652016-05-03 15:13:24 -04003124 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003125 return false;
3126 }
3127
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003128 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003129 {
Jamie Madill437fa652016-05-03 15:13:24 -04003130 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003131 return false;
3132 }
3133
3134 switch (pname)
3135 {
3136 case GL_QUERY_RESULT_EXT:
3137 case GL_QUERY_RESULT_AVAILABLE_EXT:
3138 break;
3139
3140 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003141 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003142 return false;
3143 }
3144
Geoff Lang2186c382016-10-14 10:54:54 -04003145 if (numParams)
3146 {
3147 *numParams = 1;
3148 }
3149
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003150 return true;
3151}
3152
3153bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
3154{
3155 if (!context->getExtensions().disjointTimerQuery)
3156 {
Jamie Madill437fa652016-05-03 15:13:24 -04003157 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003158 return false;
3159 }
Geoff Lang2186c382016-10-14 10:54:54 -04003160 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
3161}
3162
3163bool ValidateGetQueryObjectivRobustANGLE(Context *context,
3164 GLuint id,
3165 GLenum pname,
3166 GLsizei bufSize,
3167 GLsizei *length,
3168 GLint *params)
3169{
3170 if (!context->getExtensions().disjointTimerQuery)
3171 {
3172 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
3173 return false;
3174 }
3175
3176 if (!ValidateRobustEntryPoint(context, bufSize))
3177 {
3178 return false;
3179 }
3180
3181 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
3182 {
3183 return false;
3184 }
3185
3186 if (!ValidateRobustBufferSize(context, bufSize, *length))
3187 {
3188 return false;
3189 }
3190
3191 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003192}
3193
3194bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
3195{
3196 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04003197 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003198 {
Jamie Madill437fa652016-05-03 15:13:24 -04003199 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003200 return false;
3201 }
Geoff Lang2186c382016-10-14 10:54:54 -04003202 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
3203}
3204
3205bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
3206 GLuint id,
3207 GLenum pname,
3208 GLsizei bufSize,
3209 GLsizei *length,
3210 GLuint *params)
3211{
3212 if (!context->getExtensions().disjointTimerQuery &&
3213 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
3214 {
3215 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
3216 return false;
3217 }
3218
3219 if (!ValidateRobustEntryPoint(context, bufSize))
3220 {
3221 return false;
3222 }
3223
3224 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
3225 {
3226 return false;
3227 }
3228
3229 if (!ValidateRobustBufferSize(context, bufSize, *length))
3230 {
3231 return false;
3232 }
3233
3234 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003235}
3236
3237bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
3238{
3239 if (!context->getExtensions().disjointTimerQuery)
3240 {
Jamie Madill437fa652016-05-03 15:13:24 -04003241 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003242 return false;
3243 }
Geoff Lang2186c382016-10-14 10:54:54 -04003244 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
3245}
3246
3247bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
3248 GLuint id,
3249 GLenum pname,
3250 GLsizei bufSize,
3251 GLsizei *length,
3252 GLint64 *params)
3253{
3254 if (!context->getExtensions().disjointTimerQuery)
3255 {
3256 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
3257 return false;
3258 }
3259
3260 if (!ValidateRobustEntryPoint(context, bufSize))
3261 {
3262 return false;
3263 }
3264
3265 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
3266 {
3267 return false;
3268 }
3269
3270 if (!ValidateRobustBufferSize(context, bufSize, *length))
3271 {
3272 return false;
3273 }
3274
3275 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003276}
3277
3278bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
3279{
3280 if (!context->getExtensions().disjointTimerQuery)
3281 {
Jamie Madill437fa652016-05-03 15:13:24 -04003282 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003283 return false;
3284 }
Geoff Lang2186c382016-10-14 10:54:54 -04003285 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
3286}
3287
3288bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
3289 GLuint id,
3290 GLenum pname,
3291 GLsizei bufSize,
3292 GLsizei *length,
3293 GLuint64 *params)
3294{
3295 if (!context->getExtensions().disjointTimerQuery)
3296 {
3297 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
3298 return false;
3299 }
3300
3301 if (!ValidateRobustEntryPoint(context, bufSize))
3302 {
3303 return false;
3304 }
3305
3306 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
3307 {
3308 return false;
3309 }
3310
3311 if (!ValidateRobustBufferSize(context, bufSize, *length))
3312 {
3313 return false;
3314 }
3315
3316 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003317}
3318
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003319bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003320 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003321 GLuint program,
3322 GLint location,
3323 GLsizei count)
3324{
3325 // Check for ES31 program uniform entry points
3326 if (context->getClientVersion() < Version(3, 1))
3327 {
3328 context->handleError(Error(GL_INVALID_OPERATION));
3329 return false;
3330 }
3331
3332 const LinkedUniform *uniform = nullptr;
3333 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003334 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3335 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003336}
3337
Frank Henigmana98a6472017-02-02 21:38:32 -05003338bool ValidateProgramUniform1iv(gl::Context *context,
3339 GLuint program,
3340 GLint location,
3341 GLsizei count,
3342 const GLint *value)
3343{
3344 // Check for ES31 program uniform entry points
3345 if (context->getClientVersion() < Version(3, 1))
3346 {
3347 context->handleError(Error(GL_INVALID_OPERATION));
3348 return false;
3349 }
3350
3351 const LinkedUniform *uniform = nullptr;
3352 gl::Program *programObject = GetValidProgram(context, program);
3353 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3354 ValidateUniform1ivValue(context, uniform->type, count, value);
3355}
3356
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003357bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003358 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003359 GLuint program,
3360 GLint location,
3361 GLsizei count,
3362 GLboolean transpose)
3363{
3364 // Check for ES31 program uniform entry points
3365 if (context->getClientVersion() < Version(3, 1))
3366 {
3367 context->handleError(Error(GL_INVALID_OPERATION));
3368 return false;
3369 }
3370
3371 const LinkedUniform *uniform = nullptr;
3372 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003373 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3374 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003375}
3376
Jamie Madillc1d770e2017-04-13 17:31:24 -04003377bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04003378{
3379 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003380 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04003381 {
Jamie Madill437fa652016-05-03 15:13:24 -04003382 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003383 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04003384 }
3385
Jamie Madill62d31cb2015-09-11 13:25:51 -04003386 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003387 gl::Program *programObject = context->getGLState().getProgram();
3388 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3389 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04003390}
3391
Frank Henigmana98a6472017-02-02 21:38:32 -05003392bool ValidateUniform1iv(gl::Context *context, GLint location, GLsizei count, const GLint *value)
3393{
3394 const LinkedUniform *uniform = nullptr;
3395 gl::Program *programObject = context->getGLState().getProgram();
3396 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3397 ValidateUniform1ivValue(context, uniform->type, count, value);
3398}
3399
Jamie Madillc1d770e2017-04-13 17:31:24 -04003400bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003401 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08003402 GLint location,
3403 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04003404 GLboolean transpose)
3405{
3406 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003407 int rows = VariableRowCount(valueType);
3408 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03003409 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04003410 {
Jamie Madill437fa652016-05-03 15:13:24 -04003411 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003412 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04003413 }
3414
Martin Radev1be913c2016-07-11 17:59:16 +03003415 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04003416 {
Jamie Madill437fa652016-05-03 15:13:24 -04003417 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003418 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04003419 }
3420
Jamie Madill62d31cb2015-09-11 13:25:51 -04003421 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003422 gl::Program *programObject = context->getGLState().getProgram();
3423 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3424 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04003425}
3426
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003427bool ValidateStateQuery(ValidationContext *context,
3428 GLenum pname,
3429 GLenum *nativeType,
3430 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04003431{
3432 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
3433 {
Jamie Madill437fa652016-05-03 15:13:24 -04003434 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003435 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003436 }
3437
Jamie Madill0af26e12015-03-05 19:54:33 -05003438 const Caps &caps = context->getCaps();
3439
Jamie Madill893ab082014-05-16 16:56:10 -04003440 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
3441 {
3442 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
3443
Jamie Madill0af26e12015-03-05 19:54:33 -05003444 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04003445 {
Jamie Madill437fa652016-05-03 15:13:24 -04003446 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003447 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003448 }
3449 }
3450
3451 switch (pname)
3452 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003453 case GL_TEXTURE_BINDING_2D:
3454 case GL_TEXTURE_BINDING_CUBE_MAP:
3455 case GL_TEXTURE_BINDING_3D:
3456 case GL_TEXTURE_BINDING_2D_ARRAY:
3457 break;
3458 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3459 if (!context->getExtensions().eglStreamConsumerExternal &&
3460 !context->getExtensions().eglImageExternal)
3461 {
3462 context->handleError(Error(GL_INVALID_ENUM,
3463 "Neither NV_EGL_stream_consumer_external nor "
3464 "GL_OES_EGL_image_external extensions enabled"));
3465 return false;
3466 }
3467 break;
Jamie Madill893ab082014-05-16 16:56:10 -04003468
He Yunchaoced53ae2016-11-29 15:00:51 +08003469 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3470 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04003471 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04003472 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
3473 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04003474 {
Jamie Madill437fa652016-05-03 15:13:24 -04003475 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003476 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003477 }
3478
Jamie Madill51f40ec2016-06-15 14:06:00 -04003479 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
3480 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03003481
3482 if (framebuffer->getReadBufferState() == GL_NONE)
3483 {
3484 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3485 return false;
3486 }
3487
Jamie Madillb6bda4a2015-04-20 12:53:26 -04003488 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04003489 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04003490 {
Jamie Madill437fa652016-05-03 15:13:24 -04003491 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003492 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003493 }
3494 }
3495 break;
3496
He Yunchaoced53ae2016-11-29 15:00:51 +08003497 default:
3498 break;
Jamie Madill893ab082014-05-16 16:56:10 -04003499 }
3500
3501 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04003502 if (*numParams == 0)
3503 {
3504 return false;
3505 }
3506
3507 return true;
3508}
3509
3510bool ValidateRobustStateQuery(ValidationContext *context,
3511 GLenum pname,
3512 GLsizei bufSize,
3513 GLenum *nativeType,
3514 unsigned int *numParams)
3515{
3516 if (!ValidateRobustEntryPoint(context, bufSize))
3517 {
3518 return false;
3519 }
3520
3521 if (!ValidateStateQuery(context, pname, nativeType, numParams))
3522 {
3523 return false;
3524 }
3525
3526 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04003527 {
3528 return false;
3529 }
3530
3531 return true;
3532}
3533
Jamie Madillc29968b2016-01-20 11:17:23 -05003534bool ValidateCopyTexImageParametersBase(ValidationContext *context,
3535 GLenum target,
3536 GLint level,
3537 GLenum internalformat,
3538 bool isSubImage,
3539 GLint xoffset,
3540 GLint yoffset,
3541 GLint zoffset,
3542 GLint x,
3543 GLint y,
3544 GLsizei width,
3545 GLsizei height,
3546 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04003547 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04003548{
Jamie Madill560a8d82014-05-21 13:06:20 -04003549 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
3550 {
Jamie Madill437fa652016-05-03 15:13:24 -04003551 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003552 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003553 }
3554
He Yunchaoced53ae2016-11-29 15:00:51 +08003555 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3556 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04003557 {
Jamie Madill437fa652016-05-03 15:13:24 -04003558 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003559 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003560 }
3561
3562 if (border != 0)
3563 {
Jamie Madill437fa652016-05-03 15:13:24 -04003564 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003565 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003566 }
3567
3568 if (!ValidMipLevel(context, target, level))
3569 {
Jamie Madill437fa652016-05-03 15:13:24 -04003570 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003571 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003572 }
3573
Jamie Madill51f40ec2016-06-15 14:06:00 -04003574 const auto &state = context->getGLState();
3575 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04003576 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003577 {
Jamie Madill437fa652016-05-03 15:13:24 -04003578 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003579 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003580 }
3581
Jamie Madilldd43e6c2017-03-24 14:18:49 -04003582 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003583 {
Jamie Madill437fa652016-05-03 15:13:24 -04003584 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003585 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003586 }
3587
Martin Radev138064f2016-07-15 12:03:41 +03003588 if (readFramebuffer->getReadBufferState() == GL_NONE)
3589 {
3590 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3591 return false;
3592 }
3593
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003594 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3595 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003596 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003597 // situation is an application error that would lead to a crash in ANGLE.
3598 if (readFramebuffer->getReadColorbuffer() == nullptr)
3599 {
3600 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3601 return false;
3602 }
3603
Geoff Langaae65a42014-05-26 12:43:44 -04003604 const gl::Caps &caps = context->getCaps();
3605
Geoff Langaae65a42014-05-26 12:43:44 -04003606 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003607 switch (target)
3608 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003609 case GL_TEXTURE_2D:
3610 maxDimension = caps.max2DTextureSize;
3611 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003612
He Yunchaoced53ae2016-11-29 15:00:51 +08003613 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3614 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3615 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3616 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3617 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3618 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3619 maxDimension = caps.maxCubeMapTextureSize;
3620 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003621
He Yunchaoced53ae2016-11-29 15:00:51 +08003622 case GL_TEXTURE_2D_ARRAY:
3623 maxDimension = caps.max2DTextureSize;
3624 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003625
He Yunchaoced53ae2016-11-29 15:00:51 +08003626 case GL_TEXTURE_3D:
3627 maxDimension = caps.max3DTextureSize;
3628 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003629
He Yunchaoced53ae2016-11-29 15:00:51 +08003630 default:
3631 context->handleError(Error(GL_INVALID_ENUM));
3632 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003633 }
3634
Jamie Madillc29968b2016-01-20 11:17:23 -05003635 gl::Texture *texture =
3636 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003637 if (!texture)
3638 {
Jamie Madill437fa652016-05-03 15:13:24 -04003639 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003640 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003641 }
3642
Geoff Lang69cce582015-09-17 13:20:36 -04003643 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003644 {
Jamie Madill437fa652016-05-03 15:13:24 -04003645 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003646 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003647 }
3648
Geoff Langca271392017-04-05 12:30:00 -04003649 const gl::InternalFormat &formatInfo =
3650 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04003651
Geoff Lang966c9402017-04-18 12:38:27 -04003652 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04003653 {
Jamie Madill437fa652016-05-03 15:13:24 -04003654 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003655 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003656 }
3657
3658 if (isSubImage)
3659 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003660 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3661 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3662 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003663 {
Jamie Madill437fa652016-05-03 15:13:24 -04003664 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003665 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003666 }
3667 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003668 else
3669 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003670 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003671 {
Jamie Madill437fa652016-05-03 15:13:24 -04003672 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003673 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003674 }
3675
Geoff Langeb66a6e2016-10-31 13:06:12 -04003676 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003677 {
Jamie Madill437fa652016-05-03 15:13:24 -04003678 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003679 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003680 }
3681
3682 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003683 if (static_cast<int>(width) > maxLevelDimension ||
3684 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003685 {
Jamie Madill437fa652016-05-03 15:13:24 -04003686 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003687 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003688 }
3689 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003690
Jamie Madill0c8abca2016-07-22 20:21:26 -04003691 if (textureFormatOut)
3692 {
3693 *textureFormatOut = texture->getFormat(target, level);
3694 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003695
3696 // Detect texture copying feedback loops for WebGL.
3697 if (context->getExtensions().webglCompatibility)
3698 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05003699 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05003700 {
3701 context->handleError(Error(GL_INVALID_OPERATION,
3702 "Texture copying feedback loop formed between Framebuffer "
3703 "and specified Texture level."));
3704 return false;
3705 }
3706 }
3707
Jamie Madill560a8d82014-05-21 13:06:20 -04003708 return true;
3709}
3710
Jiajia Qind9671222016-11-29 16:30:31 +08003711bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003712{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003713 switch (mode)
3714 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003715 case GL_POINTS:
3716 case GL_LINES:
3717 case GL_LINE_LOOP:
3718 case GL_LINE_STRIP:
3719 case GL_TRIANGLES:
3720 case GL_TRIANGLE_STRIP:
3721 case GL_TRIANGLE_FAN:
3722 break;
3723 default:
3724 context->handleError(Error(GL_INVALID_ENUM));
3725 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003726 }
3727
Jamie Madill250d33f2014-06-06 17:09:03 -04003728 if (count < 0)
3729 {
Jamie Madill437fa652016-05-03 15:13:24 -04003730 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003731 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003732 }
3733
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003734 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003735
Jamie Madill250d33f2014-06-06 17:09:03 -04003736 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003737 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003738 {
Jamie Madill437fa652016-05-03 15:13:24 -04003739 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003740 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003741 }
3742
Jamie Madillcbcde722017-01-06 14:50:00 -05003743 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3744 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003745 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003746 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3747 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003748 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003749 const FramebufferAttachment *dsAttachment =
3750 framebuffer->getStencilOrDepthStencilAttachment();
3751 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003752 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003753 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003754
3755 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3756 bool differentWritemasks =
3757 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3758 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3759 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3760 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3761
3762 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003763 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003764 if (!context->getExtensions().webglCompatibility)
3765 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003766 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3767 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003768 }
Jamie Madill437fa652016-05-03 15:13:24 -04003769 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003770 return false;
3771 }
Jamie Madillac528012014-06-20 13:21:23 -04003772 }
3773
Jamie Madilldd43e6c2017-03-24 14:18:49 -04003774 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003775 {
Jamie Madill437fa652016-05-03 15:13:24 -04003776 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003777 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003778 }
3779
Geoff Lang7dd2e102014-11-10 15:19:26 -05003780 gl::Program *program = state.getProgram();
3781 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003782 {
Jamie Madill437fa652016-05-03 15:13:24 -04003783 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003784 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003785 }
3786
Yunchao Hef81ce4a2017-04-24 10:49:17 +08003787 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003788 {
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 Madilld4cfa572014-07-08 10:00:32 -04003791 }
3792
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003793 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003794 for (unsigned int uniformBlockIndex = 0;
3795 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003796 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003797 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003798 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003799 const OffsetBindingPointer<Buffer> &uniformBuffer =
3800 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003801
Geoff Lang5d124a62015-09-15 13:03:27 -04003802 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003803 {
3804 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003805 context->handleError(
3806 Error(GL_INVALID_OPERATION,
3807 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003808 return false;
3809 }
3810
Geoff Lang5d124a62015-09-15 13:03:27 -04003811 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003812 if (uniformBufferSize == 0)
3813 {
3814 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003815 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003816 }
3817
Jamie Madill62d31cb2015-09-11 13:25:51 -04003818 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003819 {
3820 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003821 context->handleError(
3822 Error(GL_INVALID_OPERATION,
3823 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003824 return false;
3825 }
3826 }
3827
Jamie Madilla4595b82017-01-11 17:36:34 -05003828 // Detect rendering feedback loops for WebGL.
3829 if (context->getExtensions().webglCompatibility)
3830 {
3831 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3832 {
3833 context->handleError(
3834 Error(GL_INVALID_OPERATION,
3835 "Rendering feedback loop formed between Framebuffer and active Texture."));
3836 return false;
3837 }
3838 }
3839
Jamie Madill250d33f2014-06-06 17:09:03 -04003840 // No-op if zero count
3841 return (count > 0);
3842}
3843
Jamie Madillc1d770e2017-04-13 17:31:24 -04003844bool ValidateDrawArraysCommon(ValidationContext *context,
3845 GLenum mode,
3846 GLint first,
3847 GLsizei count,
3848 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003849{
Jamie Madillfd716582014-06-06 17:09:04 -04003850 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003851 {
Jamie Madill437fa652016-05-03 15:13:24 -04003852 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003853 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003854 }
3855
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003856 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003857 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003858 if (curTransformFeedback && curTransformFeedback->isActive() &&
3859 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003860 {
3861 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003862 // that does not match the current transform feedback object's draw mode (if transform
3863 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003864 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003865 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003866 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003867 }
3868
Jiajia Qind9671222016-11-29 16:30:31 +08003869 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003870 {
3871 return false;
3872 }
3873
Corentin Wallez71168a02016-12-19 15:11:18 -08003874 // Check the computation of maxVertex doesn't overflow.
3875 // - first < 0 or count < 0 have been checked as an error condition
3876 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3877 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3878 ASSERT(count > 0 && first >= 0);
3879 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3880 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003881 {
3882 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3883 return false;
3884 }
3885
Corentin Wallez71168a02016-12-19 15:11:18 -08003886 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003887 {
3888 return false;
3889 }
3890
3891 return true;
3892}
3893
He Yunchaoced53ae2016-11-29 15:00:51 +08003894bool ValidateDrawArraysInstanced(Context *context,
3895 GLenum mode,
3896 GLint first,
3897 GLsizei count,
3898 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003899{
Geoff Lang407d4e72017-04-12 14:54:11 -04003900 if (context->getExtensions().webglCompatibility && !ValidateDrawInstancedANGLEAndWebGL(context))
Jamie Madillfd716582014-06-06 17:09:04 -04003901 {
3902 return false;
3903 }
3904
Geoff Lang407d4e72017-04-12 14:54:11 -04003905 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04003906}
3907
He Yunchaoced53ae2016-11-29 15:00:51 +08003908bool ValidateDrawArraysInstancedANGLE(Context *context,
3909 GLenum mode,
3910 GLint first,
3911 GLsizei count,
3912 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003913{
Geoff Lang407d4e72017-04-12 14:54:11 -04003914 if (!ValidateDrawInstancedANGLEAndWebGL(context))
Geoff Lang87a93302014-09-16 13:29:43 -04003915 {
3916 return false;
3917 }
3918
Geoff Lang407d4e72017-04-12 14:54:11 -04003919 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04003920}
3921
Jiajia Qind9671222016-11-29 16:30:31 +08003922bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003923{
Jamie Madill250d33f2014-06-06 17:09:03 -04003924 switch (type)
3925 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003926 case GL_UNSIGNED_BYTE:
3927 case GL_UNSIGNED_SHORT:
3928 break;
3929 case GL_UNSIGNED_INT:
3930 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3931 {
3932 context->handleError(Error(GL_INVALID_ENUM));
3933 return false;
3934 }
3935 break;
3936 default:
3937 context->handleError(Error(GL_INVALID_ENUM));
3938 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003939 }
3940
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003941 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003942
3943 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003944 if (curTransformFeedback && curTransformFeedback->isActive() &&
3945 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003946 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003947 // It is an invalid operation to call DrawElements, DrawRangeElements or
3948 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003949 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003950 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003951 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003952 }
3953
Jiajia Qind9671222016-11-29 16:30:31 +08003954 return true;
3955}
3956
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003957bool ValidateDrawElementsCommon(ValidationContext *context,
3958 GLenum mode,
3959 GLsizei count,
3960 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003961 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003962 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003963{
3964 if (!ValidateDrawElementsBase(context, type))
3965 return false;
3966
3967 const State &state = context->getGLState();
3968
Jamie Madill250d33f2014-06-06 17:09:03 -04003969 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003970 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003971 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003972 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04003973 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003974 }
3975
He Yunchaoced53ae2016-11-29 15:00:51 +08003976 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003977 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003978
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003979 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3980
3981 if (context->getExtensions().webglCompatibility)
3982 {
3983 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3984 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3985 {
3986 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3987 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3988 // data type passed to the call, or an INVALID_OPERATION error is generated.
3989 context->handleError(Error(GL_INVALID_OPERATION,
3990 "indices must be a multiple of the element type size."));
3991 return false;
3992 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003993
3994 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3995 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3996 // error is generated.
3997 if (reinterpret_cast<intptr_t>(indices) < 0)
3998 {
3999 context->handleError(Error(GL_INVALID_VALUE, "Offset < 0."));
4000 return false;
4001 }
Geoff Langfeb8c682017-02-13 16:07:35 -05004002 }
4003
4004 if (context->getExtensions().webglCompatibility ||
4005 !context->getGLState().areClientArraysEnabled())
4006 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05004007 if (!elementArrayBuffer && count > 0)
4008 {
4009 // [WebGL 1.0] Section 6.2 No Client Side Arrays
4010 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
4011 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
4012 context->handleError(Error(GL_INVALID_OPERATION,
4013 "There is no element array buffer bound and count > 0."));
4014 return false;
4015 }
4016 }
4017
Corentin Wallez0844f2d2017-01-31 17:02:59 -05004018 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04004019 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05004020 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04004021 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05004022 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
4023 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
4024 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
4025 constexpr uint64_t kMaxTypeSize = 8;
4026 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
4027 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
4028 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05004029
Corentin Wallezfe9306a2017-02-01 17:41:05 -05004030 uint64_t typeSize = typeBytes;
4031 uint64_t elementCount = static_cast<uint64_t>(count);
4032 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
4033
4034 // Doing the multiplication here is overflow-safe
4035 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
4036
4037 // The offset can be any value, check for overflows
4038 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
4039 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05004040 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05004041 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
Corentin Wallez0844f2d2017-01-31 17:02:59 -05004042 return false;
4043 }
4044
Corentin Wallezfe9306a2017-02-01 17:41:05 -05004045 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
4046 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05004047 {
4048 context->handleError(
4049 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
4050 return false;
4051 }
4052 }
4053 else if (!indices)
4054 {
4055 // This is an application error that would normally result in a crash,
4056 // but we catch it and return an error
4057 context->handleError(
4058 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04004059 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04004060 }
Jamie Madillae3000b2014-08-25 15:47:51 -04004061 }
4062
Jiajia Qind9671222016-11-29 16:30:31 +08004063 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07004064 {
4065 return false;
4066 }
4067
Jamie Madill9c9b40a2017-04-26 16:31:57 -04004068 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill2b976812014-08-25 15:47:49 -04004069 // TODO: offer fast path, with disabled index validation.
4070 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04004071 const auto &params = context->getParams<HasIndexRange>();
4072 const auto &indexRangeOpt = params.getIndexRange();
4073 if (!indexRangeOpt.valid())
Jamie Madill2b976812014-08-25 15:47:49 -04004074 {
Jamie Madill9c9b40a2017-04-26 16:31:57 -04004075 // Unexpected error.
4076 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04004077 }
4078
Jamie Madille79b1e12015-11-04 16:36:37 -05004079 // If we use an index greater than our maximum supported index range, return an error.
4080 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
4081 // return an error if possible here.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04004082 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
Jamie Madille79b1e12015-11-04 16:36:37 -05004083 {
Jamie Madill437fa652016-05-03 15:13:24 -04004084 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05004085 return false;
4086 }
4087
Jamie Madill9c9b40a2017-04-26 16:31:57 -04004088 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
4089 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04004090 {
4091 return false;
4092 }
4093
Geoff Lang3edfe032015-09-04 16:38:24 -04004094 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill9c9b40a2017-04-26 16:31:57 -04004095 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04004096}
4097
Jamie Madill9c9b40a2017-04-26 16:31:57 -04004098bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
4099 GLenum mode,
4100 GLsizei count,
4101 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04004102 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04004103 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04004104{
Geoff Lang407d4e72017-04-12 14:54:11 -04004105 if (context->getExtensions().webglCompatibility && !ValidateDrawInstancedANGLEAndWebGL(context))
Jamie Madillfd716582014-06-06 17:09:04 -04004106 {
4107 return false;
4108 }
4109
Jamie Madill9c9b40a2017-04-26 16:31:57 -04004110 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04004111}
4112
Geoff Lang3edfe032015-09-04 16:38:24 -04004113bool ValidateDrawElementsInstancedANGLE(Context *context,
4114 GLenum mode,
4115 GLsizei count,
4116 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04004117 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04004118 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04004119{
Geoff Lang407d4e72017-04-12 14:54:11 -04004120 if (!ValidateDrawInstancedANGLEAndWebGL(context))
Geoff Lang87a93302014-09-16 13:29:43 -04004121 {
4122 return false;
4123 }
4124
Jamie Madill9c9b40a2017-04-26 16:31:57 -04004125 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04004126}
4127
He Yunchaoced53ae2016-11-29 15:00:51 +08004128bool ValidateFramebufferTextureBase(Context *context,
4129 GLenum target,
4130 GLenum attachment,
4131 GLuint texture,
4132 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04004133{
Jamie Madill55ec3b12014-07-03 10:38:57 -04004134 if (!ValidFramebufferTarget(target))
4135 {
Jamie Madill437fa652016-05-03 15:13:24 -04004136 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04004137 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004138 }
4139
4140 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04004141 {
4142 return false;
4143 }
4144
Jamie Madill55ec3b12014-07-03 10:38:57 -04004145 if (texture != 0)
4146 {
4147 gl::Texture *tex = context->getTexture(texture);
4148
Yunchao He4f285442017-04-21 12:15:49 +08004149 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04004150 {
Jamie Madill437fa652016-05-03 15:13:24 -04004151 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04004152 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004153 }
4154
4155 if (level < 0)
4156 {
Jamie Madill437fa652016-05-03 15:13:24 -04004157 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04004158 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004159 }
4160 }
4161
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004162 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04004163 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04004164
Jamie Madill84115c92015-04-23 15:00:07 -04004165 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04004166 {
Jamie Madill437fa652016-05-03 15:13:24 -04004167 context->handleError(
4168 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04004169 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004170 }
4171
4172 return true;
4173}
4174
He Yunchaoced53ae2016-11-29 15:00:51 +08004175bool ValidateFramebufferTexture2D(Context *context,
4176 GLenum target,
4177 GLenum attachment,
4178 GLenum textarget,
4179 GLuint texture,
4180 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04004181{
He Yunchaoced53ae2016-11-29 15:00:51 +08004182 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
4183 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03004184 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
4185 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04004186 {
Jamie Madill437fa652016-05-03 15:13:24 -04004187 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04004188 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004189 }
4190
4191 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04004192 {
4193 return false;
4194 }
4195
Jamie Madill55ec3b12014-07-03 10:38:57 -04004196 if (texture != 0)
4197 {
4198 gl::Texture *tex = context->getTexture(texture);
4199 ASSERT(tex);
4200
Jamie Madill2a6564e2014-07-11 09:53:19 -04004201 const gl::Caps &caps = context->getCaps();
4202
Jamie Madill55ec3b12014-07-03 10:38:57 -04004203 switch (textarget)
4204 {
He Yunchaoced53ae2016-11-29 15:00:51 +08004205 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04004206 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04004207 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04004208 {
Jamie Madill437fa652016-05-03 15:13:24 -04004209 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04004210 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004211 }
4212 if (tex->getTarget() != GL_TEXTURE_2D)
4213 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08004214 context->handleError(Error(GL_INVALID_OPERATION,
4215 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04004216 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004217 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04004218 }
4219 break;
4220
He Yunchaoced53ae2016-11-29 15:00:51 +08004221 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4222 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4223 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4224 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4225 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4226 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04004227 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04004228 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04004229 {
Jamie Madill437fa652016-05-03 15:13:24 -04004230 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04004231 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004232 }
4233 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
4234 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08004235 context->handleError(Error(GL_INVALID_OPERATION,
4236 "Textarget must match the texture target type."));
4237 return false;
4238 }
4239 }
4240 break;
4241
4242 case GL_TEXTURE_2D_MULTISAMPLE:
4243 {
4244 if (context->getClientVersion() < ES_3_1)
4245 {
4246 context->handleError(Error(GL_INVALID_OPERATION,
4247 "Texture target requires at least OpenGL ES 3.1."));
4248 return false;
4249 }
4250
4251 if (level != 0)
4252 {
4253 context->handleError(
4254 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
4255 return false;
4256 }
4257 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
4258 {
4259 context->handleError(Error(GL_INVALID_OPERATION,
4260 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04004261 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004262 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04004263 }
4264 break;
4265
He Yunchaoced53ae2016-11-29 15:00:51 +08004266 default:
4267 context->handleError(Error(GL_INVALID_ENUM));
4268 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004269 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05004270
Jamie Madilla3944d42016-07-22 22:13:26 -04004271 const Format &format = tex->getFormat(textarget, level);
4272 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05004273 {
Jamie Madill437fa652016-05-03 15:13:24 -04004274 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05004275 return false;
4276 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04004277 }
4278
Jamie Madill570f7c82014-07-03 10:38:54 -04004279 return true;
4280}
4281
Geoff Langb1196682014-07-23 13:47:29 -04004282bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04004283{
4284 if (program == 0)
4285 {
Jamie Madill437fa652016-05-03 15:13:24 -04004286 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04004287 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04004288 }
4289
Dian Xiang769769a2015-09-09 15:20:08 -07004290 gl::Program *programObject = GetValidProgram(context, program);
4291 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05004292 {
4293 return false;
4294 }
4295
Jamie Madill0063c512014-08-25 15:47:53 -04004296 if (!programObject || !programObject->isLinked())
4297 {
Jamie Madill437fa652016-05-03 15:13:24 -04004298 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04004299 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04004300 }
4301
Geoff Lang7dd2e102014-11-10 15:19:26 -05004302 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04004303 {
Jamie Madill437fa652016-05-03 15:13:24 -04004304 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04004305 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04004306 }
4307
Jamie Madill0063c512014-08-25 15:47:53 -04004308 return true;
4309}
4310
He Yunchaoced53ae2016-11-29 15:00:51 +08004311bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04004312{
4313 return ValidateGetUniformBase(context, program, location);
4314}
4315
He Yunchaoced53ae2016-11-29 15:00:51 +08004316bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04004317{
Jamie Madill78f41802014-08-25 15:47:55 -04004318 return ValidateGetUniformBase(context, program, location);
4319}
4320
Geoff Langf41d0ee2016-10-07 13:04:23 -04004321static bool ValidateSizedGetUniform(Context *context,
4322 GLuint program,
4323 GLint location,
4324 GLsizei bufSize,
4325 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04004326{
Geoff Langf41d0ee2016-10-07 13:04:23 -04004327 if (length)
4328 {
4329 *length = 0;
4330 }
4331
Jamie Madill78f41802014-08-25 15:47:55 -04004332 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04004333 {
Jamie Madill78f41802014-08-25 15:47:55 -04004334 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04004335 }
4336
Geoff Langf41d0ee2016-10-07 13:04:23 -04004337 if (bufSize < 0)
4338 {
4339 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4340 return false;
4341 }
4342
Jamie Madilla502c742014-08-28 17:19:13 -04004343 gl::Program *programObject = context->getProgram(program);
4344 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04004345
Jamie Madill78f41802014-08-25 15:47:55 -04004346 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04004347 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08004348 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04004349 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04004350 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04004351 context->handleError(
4352 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04004353 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04004354 }
4355
Geoff Langf41d0ee2016-10-07 13:04:23 -04004356 if (length)
4357 {
Geoff Lang94177fb2016-11-14 16:12:26 -05004358 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04004359 }
4360
Jamie Madill0063c512014-08-25 15:47:53 -04004361 return true;
4362}
4363
He Yunchaoced53ae2016-11-29 15:00:51 +08004364bool ValidateGetnUniformfvEXT(Context *context,
4365 GLuint program,
4366 GLint location,
4367 GLsizei bufSize,
4368 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04004369{
Geoff Langf41d0ee2016-10-07 13:04:23 -04004370 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04004371}
4372
He Yunchaoced53ae2016-11-29 15:00:51 +08004373bool ValidateGetnUniformivEXT(Context *context,
4374 GLuint program,
4375 GLint location,
4376 GLsizei bufSize,
4377 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04004378{
Geoff Langf41d0ee2016-10-07 13:04:23 -04004379 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
4380}
4381
4382bool ValidateGetUniformfvRobustANGLE(Context *context,
4383 GLuint program,
4384 GLint location,
4385 GLsizei bufSize,
4386 GLsizei *length,
4387 GLfloat *params)
4388{
4389 if (!ValidateRobustEntryPoint(context, bufSize))
4390 {
4391 return false;
4392 }
4393
4394 // bufSize is validated in ValidateSizedGetUniform
4395 return ValidateSizedGetUniform(context, program, location, bufSize, length);
4396}
4397
4398bool ValidateGetUniformivRobustANGLE(Context *context,
4399 GLuint program,
4400 GLint location,
4401 GLsizei bufSize,
4402 GLsizei *length,
4403 GLint *params)
4404{
4405 if (!ValidateRobustEntryPoint(context, bufSize))
4406 {
4407 return false;
4408 }
4409
4410 // bufSize is validated in ValidateSizedGetUniform
4411 return ValidateSizedGetUniform(context, program, location, bufSize, length);
4412}
4413
4414bool ValidateGetUniformuivRobustANGLE(Context *context,
4415 GLuint program,
4416 GLint location,
4417 GLsizei bufSize,
4418 GLsizei *length,
4419 GLuint *params)
4420{
4421 if (!ValidateRobustEntryPoint(context, bufSize))
4422 {
4423 return false;
4424 }
4425
4426 if (context->getClientMajorVersion() < 3)
4427 {
4428 context->handleError(
4429 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
4430 return false;
4431 }
4432
4433 // bufSize is validated in ValidateSizedGetUniform
4434 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04004435}
4436
He Yunchaoced53ae2016-11-29 15:00:51 +08004437bool ValidateDiscardFramebufferBase(Context *context,
4438 GLenum target,
4439 GLsizei numAttachments,
4440 const GLenum *attachments,
4441 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07004442{
4443 if (numAttachments < 0)
4444 {
Jamie Madill437fa652016-05-03 15:13:24 -04004445 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07004446 return false;
4447 }
4448
4449 for (GLsizei i = 0; i < numAttachments; ++i)
4450 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02004451 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07004452 {
4453 if (defaultFramebuffer)
4454 {
Jamie Madill437fa652016-05-03 15:13:24 -04004455 context->handleError(Error(
4456 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07004457 return false;
4458 }
4459
4460 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
4461 {
Jamie Madill437fa652016-05-03 15:13:24 -04004462 context->handleError(Error(GL_INVALID_OPERATION,
4463 "Requested color attachment is greater than the maximum "
4464 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07004465 return false;
4466 }
4467 }
4468 else
4469 {
4470 switch (attachments[i])
4471 {
He Yunchaoced53ae2016-11-29 15:00:51 +08004472 case GL_DEPTH_ATTACHMENT:
4473 case GL_STENCIL_ATTACHMENT:
4474 case GL_DEPTH_STENCIL_ATTACHMENT:
4475 if (defaultFramebuffer)
4476 {
4477 context->handleError(
4478 Error(GL_INVALID_ENUM,
4479 "Invalid attachment when the default framebuffer is bound"));
4480 return false;
4481 }
4482 break;
4483 case GL_COLOR:
4484 case GL_DEPTH:
4485 case GL_STENCIL:
4486 if (!defaultFramebuffer)
4487 {
4488 context->handleError(
4489 Error(GL_INVALID_ENUM,
4490 "Invalid attachment when the default framebuffer is not bound"));
4491 return false;
4492 }
4493 break;
4494 default:
4495 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07004496 return false;
Austin Kinross08332632015-05-05 13:35:47 -07004497 }
4498 }
4499 }
4500
4501 return true;
4502}
4503
Austin Kinross6ee1e782015-05-29 17:05:37 -07004504bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
4505{
4506 // Note that debug marker calls must not set error state
4507
4508 if (length < 0)
4509 {
4510 return false;
4511 }
4512
4513 if (marker == nullptr)
4514 {
4515 return false;
4516 }
4517
4518 return true;
4519}
4520
4521bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
4522{
4523 // Note that debug marker calls must not set error state
4524
4525 if (length < 0)
4526 {
4527 return false;
4528 }
4529
4530 if (length > 0 && marker == nullptr)
4531 {
4532 return false;
4533 }
4534
4535 return true;
4536}
4537
Geoff Langdcab33b2015-07-21 13:03:16 -04004538bool ValidateEGLImageTargetTexture2DOES(Context *context,
4539 egl::Display *display,
4540 GLenum target,
4541 egl::Image *image)
4542{
Geoff Langa8406172015-07-21 16:53:39 -04004543 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4544 {
Jamie Madill437fa652016-05-03 15:13:24 -04004545 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004546 return false;
4547 }
4548
4549 switch (target)
4550 {
4551 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004552 if (!context->getExtensions().eglImage)
4553 {
4554 context->handleError(Error(
4555 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4556 }
4557 break;
4558
4559 case GL_TEXTURE_EXTERNAL_OES:
4560 if (!context->getExtensions().eglImageExternal)
4561 {
4562 context->handleError(Error(
4563 GL_INVALID_ENUM,
4564 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4565 }
Geoff Langa8406172015-07-21 16:53:39 -04004566 break;
4567
4568 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004569 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004570 return false;
4571 }
4572
4573 if (!display->isValidImage(image))
4574 {
Jamie Madill437fa652016-05-03 15:13:24 -04004575 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004576 return false;
4577 }
4578
4579 if (image->getSamples() > 0)
4580 {
Jamie Madill437fa652016-05-03 15:13:24 -04004581 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004582 "cannot create a 2D texture from a multisampled EGL image."));
4583 return false;
4584 }
4585
Geoff Langca271392017-04-05 12:30:00 -04004586 const TextureCaps &textureCaps =
4587 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04004588 if (!textureCaps.texturable)
4589 {
Jamie Madill437fa652016-05-03 15:13:24 -04004590 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004591 "EGL image internal format is not supported as a texture."));
4592 return false;
4593 }
4594
Geoff Langdcab33b2015-07-21 13:03:16 -04004595 return true;
4596}
4597
4598bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4599 egl::Display *display,
4600 GLenum target,
4601 egl::Image *image)
4602{
Geoff Langa8406172015-07-21 16:53:39 -04004603 if (!context->getExtensions().eglImage)
4604 {
Jamie Madill437fa652016-05-03 15:13:24 -04004605 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004606 return false;
4607 }
4608
4609 switch (target)
4610 {
4611 case GL_RENDERBUFFER:
4612 break;
4613
4614 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004615 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004616 return false;
4617 }
4618
4619 if (!display->isValidImage(image))
4620 {
Jamie Madill437fa652016-05-03 15:13:24 -04004621 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004622 return false;
4623 }
4624
Geoff Langca271392017-04-05 12:30:00 -04004625 const TextureCaps &textureCaps =
4626 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04004627 if (!textureCaps.renderable)
4628 {
Jamie Madill437fa652016-05-03 15:13:24 -04004629 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004630 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4631 return false;
4632 }
4633
Geoff Langdcab33b2015-07-21 13:03:16 -04004634 return true;
4635}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004636
4637bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4638{
Geoff Lang36167ab2015-12-07 10:27:14 -05004639 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004640 {
4641 // The default VAO should always exist
4642 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004643 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004644 return false;
4645 }
4646
4647 return true;
4648}
4649
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004650bool ValidateLinkProgram(Context *context, GLuint program)
4651{
4652 if (context->hasActiveTransformFeedback(program))
4653 {
4654 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004655 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004656 "Cannot link program while program is associated with an active "
4657 "transform feedback object."));
4658 return false;
4659 }
Jamie Madillc1d770e2017-04-13 17:31:24 -04004660
4661 Program *programObject = GetValidProgram(context, program);
4662 if (!programObject)
4663 {
4664 return false;
4665 }
4666
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004667 return true;
4668}
4669
Geoff Langc5629752015-12-07 16:29:04 -05004670bool ValidateProgramBinaryBase(Context *context,
4671 GLuint program,
4672 GLenum binaryFormat,
4673 const void *binary,
4674 GLint length)
4675{
4676 Program *programObject = GetValidProgram(context, program);
4677 if (programObject == nullptr)
4678 {
4679 return false;
4680 }
4681
4682 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4683 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4684 programBinaryFormats.end())
4685 {
Jamie Madill437fa652016-05-03 15:13:24 -04004686 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004687 return false;
4688 }
4689
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004690 if (context->hasActiveTransformFeedback(program))
4691 {
4692 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004693 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004694 "Cannot change program binary while program is associated with "
4695 "an active transform feedback object."));
4696 return false;
4697 }
4698
Geoff Langc5629752015-12-07 16:29:04 -05004699 return true;
4700}
4701
4702bool ValidateGetProgramBinaryBase(Context *context,
4703 GLuint program,
4704 GLsizei bufSize,
4705 GLsizei *length,
4706 GLenum *binaryFormat,
4707 void *binary)
4708{
4709 Program *programObject = GetValidProgram(context, program);
4710 if (programObject == nullptr)
4711 {
4712 return false;
4713 }
4714
4715 if (!programObject->isLinked())
4716 {
Jamie Madill437fa652016-05-03 15:13:24 -04004717 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004718 return false;
4719 }
4720
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004721 if (context->getCaps().programBinaryFormats.empty())
4722 {
4723 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4724 return false;
4725 }
4726
Geoff Langc5629752015-12-07 16:29:04 -05004727 return true;
4728}
Jamie Madillc29968b2016-01-20 11:17:23 -05004729
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004730bool ValidateUseProgram(Context *context, GLuint program)
4731{
4732 if (program != 0)
4733 {
4734 Program *programObject = context->getProgram(program);
4735 if (!programObject)
4736 {
4737 // ES 3.1.0 section 7.3 page 72
4738 if (context->getShader(program))
4739 {
Jamie Madill437fa652016-05-03 15:13:24 -04004740 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004741 Error(GL_INVALID_OPERATION,
4742 "Attempted to use a single shader instead of a shader program."));
4743 return false;
4744 }
4745 else
4746 {
Jamie Madill437fa652016-05-03 15:13:24 -04004747 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004748 return false;
4749 }
4750 }
4751 if (!programObject->isLinked())
4752 {
Jamie Madill437fa652016-05-03 15:13:24 -04004753 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004754 return false;
4755 }
4756 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004757 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004758 {
4759 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004760 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004761 Error(GL_INVALID_OPERATION,
4762 "Cannot change active program while transform feedback is unpaused."));
4763 return false;
4764 }
4765
4766 return true;
4767}
4768
Jamie Madillc29968b2016-01-20 11:17:23 -05004769bool ValidateCopyTexImage2D(ValidationContext *context,
4770 GLenum target,
4771 GLint level,
4772 GLenum internalformat,
4773 GLint x,
4774 GLint y,
4775 GLsizei width,
4776 GLsizei height,
4777 GLint border)
4778{
Martin Radev1be913c2016-07-11 17:59:16 +03004779 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004780 {
4781 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4782 0, x, y, width, height, border);
4783 }
4784
Martin Radev1be913c2016-07-11 17:59:16 +03004785 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004786 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4787 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004788}
Jamie Madillc29968b2016-01-20 11:17:23 -05004789
4790bool ValidateFramebufferRenderbuffer(Context *context,
4791 GLenum target,
4792 GLenum attachment,
4793 GLenum renderbuffertarget,
4794 GLuint renderbuffer)
4795{
4796 if (!ValidFramebufferTarget(target) ||
4797 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4798 {
Jamie Madill437fa652016-05-03 15:13:24 -04004799 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004800 return false;
4801 }
4802
4803 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4804 renderbuffertarget, renderbuffer);
4805}
4806
4807bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4808{
4809 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4810 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4811 {
Jamie Madill437fa652016-05-03 15:13:24 -04004812 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004813 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4814 return false;
4815 }
4816
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004817 ASSERT(context->getGLState().getDrawFramebuffer());
4818 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004819 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4820
4821 // This should come first before the check for the default frame buffer
4822 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4823 // rather than INVALID_OPERATION
4824 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4825 {
4826 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4827
4828 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004829 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4830 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004831 {
4832 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004833 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4834 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4835 // 3.1 is still a bit ambiguous about the error, but future specs are
4836 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004837 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004838 return false;
4839 }
4840 else if (bufs[colorAttachment] >= maxColorAttachment)
4841 {
Jamie Madill437fa652016-05-03 15:13:24 -04004842 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004843 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004844 return false;
4845 }
4846 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4847 frameBufferId != 0)
4848 {
4849 // INVALID_OPERATION-GL is bound to buffer and ith argument
4850 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004851 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004852 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4853 return false;
4854 }
4855 }
4856
4857 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4858 // and n is not 1 or bufs is bound to value other than BACK and NONE
4859 if (frameBufferId == 0)
4860 {
4861 if (n != 1)
4862 {
Jamie Madill437fa652016-05-03 15:13:24 -04004863 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004864 "n must be 1 when GL is bound to the default framebuffer"));
4865 return false;
4866 }
4867
4868 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4869 {
Jamie Madill437fa652016-05-03 15:13:24 -04004870 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004871 GL_INVALID_OPERATION,
4872 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4873 return false;
4874 }
4875 }
4876
4877 return true;
4878}
4879
4880bool ValidateCopyTexSubImage2D(Context *context,
4881 GLenum target,
4882 GLint level,
4883 GLint xoffset,
4884 GLint yoffset,
4885 GLint x,
4886 GLint y,
4887 GLsizei width,
4888 GLsizei height)
4889{
Martin Radev1be913c2016-07-11 17:59:16 +03004890 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004891 {
4892 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4893 yoffset, x, y, width, height, 0);
4894 }
4895
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004896 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4897 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004898}
4899
Geoff Lang496c02d2016-10-20 11:38:11 -07004900bool ValidateGetBufferPointervBase(Context *context,
4901 GLenum target,
4902 GLenum pname,
4903 GLsizei *length,
4904 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004905{
Geoff Lang496c02d2016-10-20 11:38:11 -07004906 if (length)
4907 {
4908 *length = 0;
4909 }
4910
4911 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4912 {
4913 context->handleError(
4914 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004915 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004916 return false;
4917 }
4918
Olli Etuaho4f667482016-03-30 15:56:35 +03004919 if (!ValidBufferTarget(context, target))
4920 {
Jamie Madill437fa652016-05-03 15:13:24 -04004921 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004922 return false;
4923 }
4924
Geoff Lang496c02d2016-10-20 11:38:11 -07004925 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004926 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004927 case GL_BUFFER_MAP_POINTER:
4928 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004929
Geoff Lang496c02d2016-10-20 11:38:11 -07004930 default:
4931 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4932 return false;
4933 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004934
4935 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4936 // target bound to zero generate an INVALID_OPERATION error."
4937 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004938 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004939 {
Jamie Madill437fa652016-05-03 15:13:24 -04004940 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004941 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4942 return false;
4943 }
4944
Geoff Lang496c02d2016-10-20 11:38:11 -07004945 if (length)
4946 {
4947 *length = 1;
4948 }
4949
Olli Etuaho4f667482016-03-30 15:56:35 +03004950 return true;
4951}
4952
4953bool ValidateUnmapBufferBase(Context *context, GLenum target)
4954{
4955 if (!ValidBufferTarget(context, target))
4956 {
Jamie Madill437fa652016-05-03 15:13:24 -04004957 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004958 return false;
4959 }
4960
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004961 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004962
4963 if (buffer == nullptr || !buffer->isMapped())
4964 {
Jamie Madill437fa652016-05-03 15:13:24 -04004965 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004966 return false;
4967 }
4968
4969 return true;
4970}
4971
4972bool ValidateMapBufferRangeBase(Context *context,
4973 GLenum target,
4974 GLintptr offset,
4975 GLsizeiptr length,
4976 GLbitfield access)
4977{
4978 if (!ValidBufferTarget(context, target))
4979 {
Jamie Madill437fa652016-05-03 15:13:24 -04004980 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004981 return false;
4982 }
4983
4984 if (offset < 0 || length < 0)
4985 {
Jamie Madill437fa652016-05-03 15:13:24 -04004986 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004987 return false;
4988 }
4989
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004990 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004991
4992 if (!buffer)
4993 {
Jamie Madill437fa652016-05-03 15:13:24 -04004994 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004995 return false;
4996 }
4997
4998 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004999 CheckedNumeric<size_t> checkedOffset(offset);
5000 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03005001
Jamie Madille2e406c2016-06-02 13:04:10 -04005002 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03005003 {
Jamie Madill437fa652016-05-03 15:13:24 -04005004 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03005005 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
5006 return false;
5007 }
5008
5009 // Check for invalid bits in the mask
5010 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
5011 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
5012 GL_MAP_UNSYNCHRONIZED_BIT;
5013
5014 if (access & ~(allAccessBits))
5015 {
Jamie Madill437fa652016-05-03 15:13:24 -04005016 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03005017 return false;
5018 }
5019
5020 if (length == 0)
5021 {
Jamie Madill437fa652016-05-03 15:13:24 -04005022 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03005023 return false;
5024 }
5025
5026 if (buffer->isMapped())
5027 {
Jamie Madill437fa652016-05-03 15:13:24 -04005028 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03005029 return false;
5030 }
5031
5032 // Check for invalid bit combinations
5033 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
5034 {
Jamie Madill437fa652016-05-03 15:13:24 -04005035 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03005036 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
5037 return false;
5038 }
5039
5040 GLbitfield writeOnlyBits =
5041 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
5042
5043 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
5044 {
Jamie Madill437fa652016-05-03 15:13:24 -04005045 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03005046 "Invalid access bits when mapping buffer for reading: 0x%X.",
5047 access));
5048 return false;
5049 }
5050
5051 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
5052 {
Jamie Madill437fa652016-05-03 15:13:24 -04005053 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03005054 GL_INVALID_OPERATION,
5055 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
5056 return false;
5057 }
5058 return true;
5059}
5060
5061bool ValidateFlushMappedBufferRangeBase(Context *context,
5062 GLenum target,
5063 GLintptr offset,
5064 GLsizeiptr length)
5065{
5066 if (offset < 0 || length < 0)
5067 {
Jamie Madill437fa652016-05-03 15:13:24 -04005068 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03005069 return false;
5070 }
5071
5072 if (!ValidBufferTarget(context, target))
5073 {
Jamie Madill437fa652016-05-03 15:13:24 -04005074 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03005075 return false;
5076 }
5077
Jamie Madilldfde6ab2016-06-09 07:07:18 -07005078 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03005079
5080 if (buffer == nullptr)
5081 {
Jamie Madill437fa652016-05-03 15:13:24 -04005082 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03005083 return false;
5084 }
5085
5086 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
5087 {
Jamie Madill437fa652016-05-03 15:13:24 -04005088 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03005089 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
5090 return false;
5091 }
5092
5093 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04005094 CheckedNumeric<size_t> checkedOffset(offset);
5095 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03005096
Jamie Madille2e406c2016-06-02 13:04:10 -04005097 if (!checkedSize.IsValid() ||
5098 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03005099 {
Jamie Madill437fa652016-05-03 15:13:24 -04005100 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03005101 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
5102 return false;
5103 }
5104
5105 return true;
5106}
5107
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005108bool ValidateGenerateMipmap(Context *context, GLenum target)
5109{
5110 if (!ValidTextureTarget(context, target))
5111 {
5112 context->handleError(Error(GL_INVALID_ENUM));
5113 return false;
5114 }
5115
5116 Texture *texture = context->getTargetTexture(target);
5117
5118 if (texture == nullptr)
5119 {
5120 context->handleError(Error(GL_INVALID_OPERATION));
5121 return false;
5122 }
5123
5124 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5125
5126 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5127 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5128 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5129 {
5130 context->handleError(Error(GL_INVALID_OPERATION));
5131 return false;
5132 }
5133
Jamie Madilla3944d42016-07-22 22:13:26 -04005134 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
5135 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
Geoff Langca271392017-04-05 12:30:00 -04005136 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005137
5138 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
5139 // unsized formats or that are color renderable and filterable. Since we do not track if
5140 // the texture was created with sized or unsized format (only sized formats are stored),
5141 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
5142 // be able to) because they aren't color renderable. Simply do a special case for LUMA
5143 // textures since they're the only texture format that can be created with unsized formats
5144 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
5145 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04005146 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
5147 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005148 {
5149 context->handleError(Error(GL_INVALID_OPERATION));
5150 return false;
5151 }
5152
5153 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04005154 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005155 {
5156 context->handleError(Error(GL_INVALID_OPERATION));
5157 return false;
5158 }
5159
5160 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05005161 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005162 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5163 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5164 {
Geoff Lang55482a12016-11-21 16:54:01 -05005165 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005166 context->handleError(Error(GL_INVALID_OPERATION));
5167 return false;
5168 }
5169
5170 // Cube completeness check
5171 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
5172 {
5173 context->handleError(Error(GL_INVALID_OPERATION));
5174 return false;
5175 }
5176
5177 return true;
5178}
5179
Olli Etuaho41997e72016-03-10 13:38:39 +02005180bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5181{
5182 return ValidateGenOrDelete(context, n);
5183}
5184
5185bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5186{
5187 return ValidateGenOrDelete(context, n);
5188}
5189
5190bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5191{
5192 return ValidateGenOrDelete(context, n);
5193}
5194
5195bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5196{
5197 return ValidateGenOrDelete(context, n);
5198}
5199
5200bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5201{
5202 return ValidateGenOrDelete(context, n);
5203}
5204
5205bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5206{
5207 return ValidateGenOrDelete(context, n);
5208}
5209
5210bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5211{
5212 return ValidateGenOrDelete(context, n);
5213}
5214
5215bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5216{
5217 return ValidateGenOrDelete(context, n);
5218}
5219
5220bool ValidateGenOrDelete(Context *context, GLint n)
5221{
5222 if (n < 0)
5223 {
Jamie Madill437fa652016-05-03 15:13:24 -04005224 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02005225 return false;
5226 }
5227 return true;
5228}
5229
Geoff Langf41a7152016-09-19 15:11:17 -04005230bool ValidateEnable(Context *context, GLenum cap)
5231{
5232 if (!ValidCap(context, cap, false))
5233 {
5234 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5235 return false;
5236 }
5237
5238 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5239 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5240 {
5241 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
5242 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
5243
5244 // We also output an error message to the debugger window if tracing is active, so that
5245 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05005246 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04005247 return false;
5248 }
5249
5250 return true;
5251}
5252
5253bool ValidateDisable(Context *context, GLenum cap)
5254{
5255 if (!ValidCap(context, cap, false))
5256 {
5257 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5258 return false;
5259 }
5260
5261 return true;
5262}
5263
5264bool ValidateIsEnabled(Context *context, GLenum cap)
5265{
5266 if (!ValidCap(context, cap, true))
5267 {
5268 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5269 return false;
5270 }
5271
5272 return true;
5273}
5274
Geoff Langff5b2d52016-09-07 11:32:23 -04005275bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
5276{
5277 if (!context->getExtensions().robustClientMemory)
5278 {
5279 context->handleError(
5280 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
5281 return false;
5282 }
5283
5284 if (bufSize < 0)
5285 {
5286 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
5287 return false;
5288 }
5289
5290 return true;
5291}
5292
Geoff Lang2e43dbb2016-10-14 12:27:35 -04005293bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
5294{
5295 if (bufSize < numParams)
5296 {
5297 context->handleError(Error(GL_INVALID_OPERATION,
5298 "%u parameters are required but %i were provided.", numParams,
5299 bufSize));
5300 return false;
5301 }
5302
5303 return true;
5304}
5305
Geoff Langff5b2d52016-09-07 11:32:23 -04005306bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5307 GLenum target,
5308 GLenum attachment,
5309 GLenum pname,
5310 GLsizei *numParams)
5311{
5312 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
Yunchao He33151a52017-04-13 09:58:17 +08005313 if (numParams)
5314 {
5315 *numParams = 1;
5316 }
Geoff Langff5b2d52016-09-07 11:32:23 -04005317
5318 if (!ValidFramebufferTarget(target))
5319 {
5320 context->handleError(Error(GL_INVALID_ENUM));
5321 return false;
5322 }
5323
5324 int clientVersion = context->getClientMajorVersion();
5325
5326 switch (pname)
5327 {
5328 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5329 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5330 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
5331 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
5332 break;
5333
5334 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
5335 if (clientVersion < 3 && !context->getExtensions().sRGB)
5336 {
5337 context->handleError(Error(GL_INVALID_ENUM));
5338 return false;
5339 }
5340 break;
5341
5342 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
5343 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
5344 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
5345 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
5346 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
5347 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
5348 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
5349 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
5350 if (clientVersion < 3)
5351 {
5352 context->handleError(Error(GL_INVALID_ENUM));
5353 return false;
5354 }
5355 break;
5356
5357 default:
5358 context->handleError(Error(GL_INVALID_ENUM));
5359 return false;
5360 }
5361
5362 // Determine if the attachment is a valid enum
5363 switch (attachment)
5364 {
5365 case GL_BACK:
5366 case GL_FRONT:
5367 case GL_DEPTH:
5368 case GL_STENCIL:
5369 case GL_DEPTH_STENCIL_ATTACHMENT:
5370 if (clientVersion < 3)
5371 {
5372 context->handleError(Error(GL_INVALID_ENUM));
5373 return false;
5374 }
5375 break;
5376
5377 case GL_DEPTH_ATTACHMENT:
5378 case GL_STENCIL_ATTACHMENT:
5379 break;
5380
5381 default:
5382 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
5383 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
5384 {
5385 context->handleError(Error(GL_INVALID_ENUM));
5386 return false;
5387 }
5388 break;
5389 }
5390
5391 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
5392 ASSERT(framebuffer);
5393
5394 if (framebuffer->id() == 0)
5395 {
5396 if (clientVersion < 3)
5397 {
5398 context->handleError(Error(GL_INVALID_OPERATION));
5399 return false;
5400 }
5401
5402 switch (attachment)
5403 {
5404 case GL_BACK:
5405 case GL_DEPTH:
5406 case GL_STENCIL:
5407 break;
5408
5409 default:
5410 context->handleError(Error(GL_INVALID_OPERATION));
5411 return false;
5412 }
5413 }
5414 else
5415 {
5416 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
5417 {
5418 // Valid attachment query
5419 }
5420 else
5421 {
5422 switch (attachment)
5423 {
5424 case GL_DEPTH_ATTACHMENT:
5425 case GL_STENCIL_ATTACHMENT:
5426 break;
5427
5428 case GL_DEPTH_STENCIL_ATTACHMENT:
5429 if (!framebuffer->hasValidDepthStencil())
5430 {
5431 context->handleError(Error(GL_INVALID_OPERATION));
5432 return false;
5433 }
5434 break;
5435
5436 default:
5437 context->handleError(Error(GL_INVALID_OPERATION));
5438 return false;
5439 }
5440 }
5441 }
5442
5443 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
5444 if (attachmentObject)
5445 {
5446 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
5447 attachmentObject->type() == GL_TEXTURE ||
5448 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
5449
5450 switch (pname)
5451 {
5452 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5453 if (attachmentObject->type() != GL_RENDERBUFFER &&
5454 attachmentObject->type() != GL_TEXTURE)
5455 {
5456 context->handleError(Error(GL_INVALID_ENUM));
5457 return false;
5458 }
5459 break;
5460
5461 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
5462 if (attachmentObject->type() != GL_TEXTURE)
5463 {
5464 context->handleError(Error(GL_INVALID_ENUM));
5465 return false;
5466 }
5467 break;
5468
5469 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
5470 if (attachmentObject->type() != GL_TEXTURE)
5471 {
5472 context->handleError(Error(GL_INVALID_ENUM));
5473 return false;
5474 }
5475 break;
5476
5477 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
5478 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
5479 {
5480 context->handleError(Error(GL_INVALID_OPERATION));
5481 return false;
5482 }
5483 break;
5484
5485 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
5486 if (attachmentObject->type() != GL_TEXTURE)
5487 {
5488 context->handleError(Error(GL_INVALID_ENUM));
5489 return false;
5490 }
5491 break;
5492
5493 default:
5494 break;
5495 }
5496 }
5497 else
5498 {
5499 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
5500 // is NONE, then querying any other pname will generate INVALID_ENUM.
5501
5502 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
5503 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
5504 // INVALID_OPERATION for all other pnames
5505
5506 switch (pname)
5507 {
5508 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5509 break;
5510
5511 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5512 if (clientVersion < 3)
5513 {
5514 context->handleError(Error(GL_INVALID_ENUM));
5515 return false;
5516 }
5517 break;
5518
5519 default:
5520 if (clientVersion < 3)
5521 {
5522 context->handleError(Error(GL_INVALID_ENUM));
5523 return false;
5524 }
5525 else
5526 {
5527 context->handleError(Error(GL_INVALID_OPERATION));
5528 return false;
5529 }
5530 }
5531 }
5532
5533 return true;
5534}
5535
5536bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5537 GLenum target,
5538 GLenum attachment,
5539 GLenum pname,
5540 GLsizei bufSize,
5541 GLsizei *numParams)
5542{
5543 if (!ValidateRobustEntryPoint(context, bufSize))
5544 {
5545 return false;
5546 }
5547
5548 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5549 {
5550 return false;
5551 }
5552
5553 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5554 {
5555 return false;
5556 }
5557
5558 return true;
5559}
5560
5561bool ValidateGetBufferParameteriv(ValidationContext *context,
5562 GLenum target,
5563 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005564 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005565{
Geoff Langebebe1c2016-10-14 12:01:31 -04005566 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005567}
5568
5569bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5570 GLenum target,
5571 GLenum pname,
5572 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005573 GLsizei *length,
5574 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005575{
5576 if (!ValidateRobustEntryPoint(context, bufSize))
5577 {
5578 return false;
5579 }
5580
Geoff Langebebe1c2016-10-14 12:01:31 -04005581 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005582 {
5583 return false;
5584 }
5585
Geoff Langebebe1c2016-10-14 12:01:31 -04005586 if (!ValidateRobustBufferSize(context, bufSize, *length))
5587 {
5588 return false;
5589 }
5590
5591 return true;
5592}
5593
5594bool ValidateGetBufferParameteri64v(ValidationContext *context,
5595 GLenum target,
5596 GLenum pname,
5597 GLint64 *params)
5598{
5599 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5600}
5601
5602bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5603 GLenum target,
5604 GLenum pname,
5605 GLsizei bufSize,
5606 GLsizei *length,
5607 GLint64 *params)
5608{
5609 if (!ValidateRobustEntryPoint(context, bufSize))
5610 {
5611 return false;
5612 }
5613
5614 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5615 {
5616 return false;
5617 }
5618
5619 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005620 {
5621 return false;
5622 }
5623
5624 return true;
5625}
5626
5627bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5628{
5629 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08005630 if (numParams)
5631 {
5632 *numParams = 1;
5633 }
Geoff Langff5b2d52016-09-07 11:32:23 -04005634
5635 Program *programObject = GetValidProgram(context, program);
5636 if (!programObject)
5637 {
5638 return false;
5639 }
5640
5641 switch (pname)
5642 {
5643 case GL_DELETE_STATUS:
5644 case GL_LINK_STATUS:
5645 case GL_VALIDATE_STATUS:
5646 case GL_INFO_LOG_LENGTH:
5647 case GL_ATTACHED_SHADERS:
5648 case GL_ACTIVE_ATTRIBUTES:
5649 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5650 case GL_ACTIVE_UNIFORMS:
5651 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5652 break;
5653
5654 case GL_PROGRAM_BINARY_LENGTH:
5655 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5656 {
5657 context->handleError(Error(GL_INVALID_ENUM,
5658 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5659 "GL_OES_get_program_binary or ES 3.0."));
5660 return false;
5661 }
5662 break;
5663
5664 case GL_ACTIVE_UNIFORM_BLOCKS:
5665 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5666 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5667 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5668 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5669 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5670 if (context->getClientMajorVersion() < 3)
5671 {
5672 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5673 return false;
5674 }
5675 break;
5676
Yunchao He61afff12017-03-14 15:34:03 +08005677 case GL_PROGRAM_SEPARABLE:
5678 if (context->getClientVersion() < Version(3, 1))
5679 {
5680 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.1."));
5681 return false;
5682 }
5683 break;
5684
Geoff Langff5b2d52016-09-07 11:32:23 -04005685 default:
5686 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5687 return false;
5688 }
5689
5690 return true;
5691}
5692
5693bool ValidateGetProgramivRobustANGLE(Context *context,
5694 GLuint program,
5695 GLenum pname,
5696 GLsizei bufSize,
5697 GLsizei *numParams)
5698{
5699 if (!ValidateRobustEntryPoint(context, bufSize))
5700 {
5701 return false;
5702 }
5703
5704 if (!ValidateGetProgramiv(context, program, pname, numParams))
5705 {
5706 return false;
5707 }
5708
5709 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5710 {
5711 return false;
5712 }
5713
5714 return true;
5715}
5716
Geoff Lang740d9022016-10-07 11:20:52 -04005717bool ValidateGetRenderbufferParameteriv(Context *context,
5718 GLenum target,
5719 GLenum pname,
5720 GLint *params)
5721{
5722 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5723}
5724
5725bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5726 GLenum target,
5727 GLenum pname,
5728 GLsizei bufSize,
5729 GLsizei *length,
5730 GLint *params)
5731{
5732 if (!ValidateRobustEntryPoint(context, bufSize))
5733 {
5734 return false;
5735 }
5736
5737 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5738 {
5739 return false;
5740 }
5741
5742 if (!ValidateRobustBufferSize(context, bufSize, *length))
5743 {
5744 return false;
5745 }
5746
5747 return true;
5748}
5749
Geoff Langd7d0ed32016-10-07 11:33:51 -04005750bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5751{
5752 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5753}
5754
5755bool ValidateGetShaderivRobustANGLE(Context *context,
5756 GLuint shader,
5757 GLenum pname,
5758 GLsizei bufSize,
5759 GLsizei *length,
5760 GLint *params)
5761{
5762 if (!ValidateRobustEntryPoint(context, bufSize))
5763 {
5764 return false;
5765 }
5766
5767 if (!ValidateGetShaderivBase(context, shader, pname, length))
5768 {
5769 return false;
5770 }
5771
5772 if (!ValidateRobustBufferSize(context, bufSize, *length))
5773 {
5774 return false;
5775 }
5776
5777 return true;
5778}
5779
Geoff Langc1984ed2016-10-07 12:41:00 -04005780bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5781{
5782 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5783}
5784
5785bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5786 GLenum target,
5787 GLenum pname,
5788 GLsizei bufSize,
5789 GLsizei *length,
5790 GLfloat *params)
5791{
5792 if (!ValidateRobustEntryPoint(context, bufSize))
5793 {
5794 return false;
5795 }
5796
5797 if (!ValidateGetTexParameterBase(context, target, pname, length))
5798 {
5799 return false;
5800 }
5801
5802 if (!ValidateRobustBufferSize(context, bufSize, *length))
5803 {
5804 return false;
5805 }
5806
5807 return true;
5808}
5809
5810bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5811{
5812 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5813}
5814
5815bool ValidateGetTexParameterivRobustANGLE(Context *context,
5816 GLenum target,
5817 GLenum pname,
5818 GLsizei bufSize,
5819 GLsizei *length,
5820 GLint *params)
5821{
5822 if (!ValidateRobustEntryPoint(context, bufSize))
5823 {
5824 return false;
5825 }
5826
5827 if (!ValidateGetTexParameterBase(context, target, pname, length))
5828 {
5829 return false;
5830 }
5831
5832 if (!ValidateRobustBufferSize(context, bufSize, *length))
5833 {
5834 return false;
5835 }
5836
5837 return true;
5838}
5839
5840bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5841{
5842 return ValidateTexParameterBase(context, target, pname, -1, &param);
5843}
5844
5845bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5846{
5847 return ValidateTexParameterBase(context, target, pname, -1, params);
5848}
5849
5850bool ValidateTexParameterfvRobustANGLE(Context *context,
5851 GLenum target,
5852 GLenum pname,
5853 GLsizei bufSize,
5854 const GLfloat *params)
5855{
5856 if (!ValidateRobustEntryPoint(context, bufSize))
5857 {
5858 return false;
5859 }
5860
5861 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5862}
5863
5864bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5865{
5866 return ValidateTexParameterBase(context, target, pname, -1, &param);
5867}
5868
5869bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5870{
5871 return ValidateTexParameterBase(context, target, pname, -1, params);
5872}
5873
5874bool ValidateTexParameterivRobustANGLE(Context *context,
5875 GLenum target,
5876 GLenum pname,
5877 GLsizei bufSize,
5878 const GLint *params)
5879{
5880 if (!ValidateRobustEntryPoint(context, bufSize))
5881 {
5882 return false;
5883 }
5884
5885 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5886}
5887
5888bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5889{
5890 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5891}
5892
5893bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5894 GLuint sampler,
5895 GLenum pname,
5896 GLuint bufSize,
5897 GLsizei *length,
5898 GLfloat *params)
5899{
5900 if (!ValidateRobustEntryPoint(context, bufSize))
5901 {
5902 return false;
5903 }
5904
5905 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5906 {
5907 return false;
5908 }
5909
5910 if (!ValidateRobustBufferSize(context, bufSize, *length))
5911 {
5912 return false;
5913 }
5914
5915 return true;
5916}
5917
5918bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5919{
5920 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5921}
5922
5923bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5924 GLuint sampler,
5925 GLenum pname,
5926 GLuint bufSize,
5927 GLsizei *length,
5928 GLint *params)
5929{
5930 if (!ValidateRobustEntryPoint(context, bufSize))
5931 {
5932 return false;
5933 }
5934
5935 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5936 {
5937 return false;
5938 }
5939
5940 if (!ValidateRobustBufferSize(context, bufSize, *length))
5941 {
5942 return false;
5943 }
5944
5945 return true;
5946}
5947
5948bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5949{
5950 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5951}
5952
5953bool ValidateSamplerParameterfv(Context *context,
5954 GLuint sampler,
5955 GLenum pname,
5956 const GLfloat *params)
5957{
5958 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5959}
5960
5961bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5962 GLuint sampler,
5963 GLenum pname,
5964 GLsizei bufSize,
5965 const GLfloat *params)
5966{
5967 if (!ValidateRobustEntryPoint(context, bufSize))
5968 {
5969 return false;
5970 }
5971
5972 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5973}
5974
5975bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5976{
5977 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5978}
5979
5980bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5981{
5982 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5983}
5984
5985bool ValidateSamplerParameterivRobustANGLE(Context *context,
5986 GLuint sampler,
5987 GLenum pname,
5988 GLsizei bufSize,
5989 const GLint *params)
5990{
5991 if (!ValidateRobustEntryPoint(context, bufSize))
5992 {
5993 return false;
5994 }
5995
5996 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5997}
5998
Geoff Lang0b031062016-10-13 14:30:04 -04005999bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
6000{
6001 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6002}
6003
6004bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
6005 GLuint index,
6006 GLenum pname,
6007 GLsizei bufSize,
6008 GLsizei *length,
6009 GLfloat *params)
6010{
6011 if (!ValidateRobustEntryPoint(context, bufSize))
6012 {
6013 return false;
6014 }
6015
6016 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
6017 {
6018 return false;
6019 }
6020
6021 if (!ValidateRobustBufferSize(context, bufSize, *length))
6022 {
6023 return false;
6024 }
6025
6026 return true;
6027}
6028
6029bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
6030{
6031 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6032}
6033
6034bool ValidateGetVertexAttribivRobustANGLE(Context *context,
6035 GLuint index,
6036 GLenum pname,
6037 GLsizei bufSize,
6038 GLsizei *length,
6039 GLint *params)
6040{
6041 if (!ValidateRobustEntryPoint(context, bufSize))
6042 {
6043 return false;
6044 }
6045
6046 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
6047 {
6048 return false;
6049 }
6050
6051 if (!ValidateRobustBufferSize(context, bufSize, *length))
6052 {
6053 return false;
6054 }
6055
6056 return true;
6057}
6058
6059bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
6060{
6061 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
6062}
6063
6064bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
6065 GLuint index,
6066 GLenum pname,
6067 GLsizei bufSize,
6068 GLsizei *length,
6069 void **pointer)
6070{
6071 if (!ValidateRobustEntryPoint(context, bufSize))
6072 {
6073 return false;
6074 }
6075
6076 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
6077 {
6078 return false;
6079 }
6080
6081 if (!ValidateRobustBufferSize(context, bufSize, *length))
6082 {
6083 return false;
6084 }
6085
6086 return true;
6087}
6088
6089bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
6090{
6091 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
6092}
6093
6094bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
6095 GLuint index,
6096 GLenum pname,
6097 GLsizei bufSize,
6098 GLsizei *length,
6099 GLint *params)
6100{
6101 if (!ValidateRobustEntryPoint(context, bufSize))
6102 {
6103 return false;
6104 }
6105
6106 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
6107 {
6108 return false;
6109 }
6110
6111 if (!ValidateRobustBufferSize(context, bufSize, *length))
6112 {
6113 return false;
6114 }
6115
6116 return true;
6117}
6118
6119bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
6120{
6121 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
6122}
6123
6124bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
6125 GLuint index,
6126 GLenum pname,
6127 GLsizei bufSize,
6128 GLsizei *length,
6129 GLuint *params)
6130{
6131 if (!ValidateRobustEntryPoint(context, bufSize))
6132 {
6133 return false;
6134 }
6135
6136 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
6137 {
6138 return false;
6139 }
6140
6141 if (!ValidateRobustBufferSize(context, bufSize, *length))
6142 {
6143 return false;
6144 }
6145
6146 return true;
6147}
6148
Geoff Lang6899b872016-10-14 11:30:13 -04006149bool ValidateGetActiveUniformBlockiv(Context *context,
6150 GLuint program,
6151 GLuint uniformBlockIndex,
6152 GLenum pname,
6153 GLint *params)
6154{
6155 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
6156}
6157
6158bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
6159 GLuint program,
6160 GLuint uniformBlockIndex,
6161 GLenum pname,
6162 GLsizei bufSize,
6163 GLsizei *length,
6164 GLint *params)
6165{
6166 if (!ValidateRobustEntryPoint(context, bufSize))
6167 {
6168 return false;
6169 }
6170
6171 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
6172 {
6173 return false;
6174 }
6175
6176 if (!ValidateRobustBufferSize(context, bufSize, *length))
6177 {
6178 return false;
6179 }
6180
6181 return true;
6182}
6183
Geoff Lang0a9661f2016-10-20 10:59:20 -07006184bool ValidateGetInternalFormativ(Context *context,
6185 GLenum target,
6186 GLenum internalformat,
6187 GLenum pname,
6188 GLsizei bufSize,
6189 GLint *params)
6190{
6191 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
6192 nullptr);
6193}
6194
6195bool ValidateGetInternalFormativRobustANGLE(Context *context,
6196 GLenum target,
6197 GLenum internalformat,
6198 GLenum pname,
6199 GLsizei bufSize,
6200 GLsizei *length,
6201 GLint *params)
6202{
6203 if (!ValidateRobustEntryPoint(context, bufSize))
6204 {
6205 return false;
6206 }
6207
6208 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
6209 {
6210 return false;
6211 }
6212
6213 if (!ValidateRobustBufferSize(context, bufSize, *length))
6214 {
6215 return false;
6216 }
6217
6218 return true;
6219}
6220
Shao80957d92017-02-20 21:25:59 +08006221bool ValidateVertexFormatBase(ValidationContext *context,
6222 GLuint attribIndex,
6223 GLint size,
6224 GLenum type,
6225 GLboolean pureInteger)
6226{
6227 const Caps &caps = context->getCaps();
6228 if (attribIndex >= caps.maxVertexAttributes)
6229 {
6230 context->handleError(
6231 Error(GL_INVALID_VALUE, "attribindex must be smaller than MAX_VERTEX_ATTRIBS."));
6232 return false;
6233 }
6234
6235 if (size < 1 || size > 4)
6236 {
6237 context->handleError(Error(GL_INVALID_VALUE, "size must be between one and four."));
6238 }
6239
6240 switch (type)
6241 {
6242 case GL_BYTE:
6243 case GL_UNSIGNED_BYTE:
6244 case GL_SHORT:
6245 case GL_UNSIGNED_SHORT:
6246 break;
6247
6248 case GL_INT:
6249 case GL_UNSIGNED_INT:
6250 if (context->getClientMajorVersion() < 3)
6251 {
6252 context->handleError(
6253 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
6254 return false;
6255 }
6256 break;
6257
6258 case GL_FIXED:
6259 case GL_FLOAT:
6260 if (pureInteger)
6261 {
6262 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
6263 return false;
6264 }
6265 break;
6266
6267 case GL_HALF_FLOAT:
6268 if (context->getClientMajorVersion() < 3)
6269 {
6270 context->handleError(
6271 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
6272 return false;
6273 }
6274 if (pureInteger)
6275 {
6276 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
6277 return false;
6278 }
6279 break;
6280
6281 case GL_INT_2_10_10_10_REV:
6282 case GL_UNSIGNED_INT_2_10_10_10_REV:
6283 if (context->getClientMajorVersion() < 3)
6284 {
6285 context->handleError(
6286 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
6287 return false;
6288 }
6289 if (pureInteger)
6290 {
6291 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
6292 return false;
6293 }
6294 if (size != 4)
6295 {
6296 context->handleError(Error(GL_INVALID_OPERATION,
6297 "Type is INT_2_10_10_10_REV or "
6298 "UNSIGNED_INT_2_10_10_10_REV and size is not 4."));
6299 return false;
6300 }
6301 break;
6302
6303 default:
6304 context->handleError(Error(GL_INVALID_ENUM, "Invalid vertex type."));
6305 return false;
6306 }
6307
6308 return true;
6309}
6310
Geoff Lang76e65652017-03-27 14:58:02 -04006311// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
6312// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
6313// specified clear value and the type of a buffer that is being cleared generates an
6314// INVALID_OPERATION error instead of producing undefined results
6315bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
6316 GLint drawbuffer,
6317 const GLenum *validComponentTypes,
6318 size_t validComponentTypeCount)
6319{
6320 const FramebufferAttachment *attachment =
6321 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
6322 if (attachment)
6323 {
6324 GLenum componentType = attachment->getFormat().info->componentType;
6325 const GLenum *end = validComponentTypes + validComponentTypeCount;
6326 if (std::find(validComponentTypes, end, componentType) == end)
6327 {
6328 context->handleError(
6329 Error(GL_INVALID_OPERATION,
6330 "No defined conversion between clear value and attachment format."));
6331 return false;
6332 }
6333 }
6334
6335 return true;
6336}
6337
Corentin Wallezb2931602017-04-11 15:58:57 -04006338bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
6339 GLsizei imageSize,
6340 GLsizei dataSize)
6341{
6342 if (!ValidateRobustEntryPoint(context, dataSize))
6343 {
6344 return false;
6345 }
6346
6347 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
6348 if (pixelUnpackBuffer == nullptr)
6349 {
6350 if (dataSize < imageSize)
6351 {
6352 context->handleError(
6353 Error(GL_INVALID_OPERATION, "dataSize must be at least %i.", imageSize));
6354 }
6355 }
6356 return true;
6357}
6358
Jamie Madillc29968b2016-01-20 11:17:23 -05006359} // namespace gl