blob: a4efd0367a405d37dfa70938abdcd4b878d4b949 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES2.h"
12#include "libANGLE/validationES3.h"
13#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040014#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Texture.h"
16#include "libANGLE/Framebuffer.h"
17#include "libANGLE/FramebufferAttachment.h"
18#include "libANGLE/formatutils.h"
Geoff Langa8406172015-07-21 16:53:39 -040019#include "libANGLE/Image.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/Query.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050021#include "libANGLE/Program.h"
22#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/TransformFeedback.h"
24#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025
26#include "common/mathutil.h"
27#include "common/utilities.h"
28
Jamie Madille2e406c2016-06-02 13:04:10 -040029using namespace angle;
30
Geoff Lange8ebe7f2013-08-05 15:03:13 -040031namespace gl
32{
Jamie Madille79b1e12015-11-04 16:36:37 -050033const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
34
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Corentin Wallez92db6942016-12-09 13:10:36 -050037bool ValidateDrawAttribs(ValidationContext *context,
38 GLint primcount,
39 GLint maxVertex,
40 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040041{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070042 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040043 const gl::Program *program = state.getProgram();
44
Corentin Wallez327411e2016-12-09 11:09:17 -050045 bool webglCompatibility = context->getExtensions().webglCompatibility;
46
He Yunchaoced53ae2016-11-29 15:00:51 +080047 const VertexArray *vao = state.getVertexArray();
48 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080049 const auto &vertexBindings = vao->getVertexBindings();
He Yunchaoced53ae2016-11-29 15:00:51 +080050 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040051 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
52 {
53 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallezfd456442016-12-21 17:57:00 -050054 if (!program->isAttribLocationActive(attributeIndex) || !attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040055 {
Corentin Wallezfd456442016-12-21 17:57:00 -050056 continue;
57 }
Jamie Madill1ca74672015-07-21 15:14:11 -040058
Jiawei-Shao2597fb62016-12-09 16:38:02 +080059 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
Corentin Wallezfd456442016-12-21 17:57:00 -050060 // If we have no buffer, then we either get an error, or there are no more checks to be done.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080061 gl::Buffer *buffer = binding.buffer.get();
Corentin Wallezfd456442016-12-21 17:57:00 -050062 if (!buffer)
63 {
Geoff Langfeb8c682017-02-13 16:07:35 -050064 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050065 {
66 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050067 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
68 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
69 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
70 // error.
Corentin Wallez327411e2016-12-09 11:09:17 -050071 context->handleError(
72 Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer."));
Corentin Wallezfd456442016-12-21 17:57:00 -050073 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050074 }
Corentin Wallezfd456442016-12-21 17:57:00 -050075 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040076 {
77 // This is an application error that would normally result in a crash,
78 // but we catch it and return an error
Corentin Wallezfd456442016-12-21 17:57:00 -050079 context->handleError(
80 Error(GL_INVALID_OPERATION,
81 "An enabled vertex array has no buffer and no pointer."));
Jamie Madill1ca74672015-07-21 15:14:11 -040082 return false;
83 }
Corentin Wallezfd456442016-12-21 17:57:00 -050084 continue;
85 }
86
87 // If we're drawing zero vertices, we have enough data.
88 if (vertexCount <= 0 || primcount <= 0)
89 {
90 continue;
91 }
92
93 GLint maxVertexElement = 0;
Jiawei-Shao2597fb62016-12-09 16:38:02 +080094 if (binding.divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -050095 {
96 maxVertexElement = maxVertex;
97 }
98 else
99 {
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800100 maxVertexElement = (primcount - 1) / binding.divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500101 }
102
103 // We do manual overflow checks here instead of using safe_math.h because it was
104 // a bottleneck. Thanks to some properties of GL we know inequalities that can
105 // help us make the overflow checks faster.
106
107 // The max possible attribSize is 16 for a vector of 4 32 bit values.
108 constexpr uint64_t kMaxAttribSize = 16;
109 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
110 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
111
112 // We know attribStride is given as a GLsizei which is typedefed to int.
113 // We also know an upper bound for attribSize.
114 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800115 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500116 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
117 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
118
119 // Computing the max offset using uint64_t without attrib.offset is overflow
120 // safe. Note: Last vertex element does not take the full stride!
121 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
122 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
123
124 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800125 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
126 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500127 {
128 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
129 return false;
130 }
131 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
132
133 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
134 // We can return INVALID_OPERATION if our vertex attribute does not have
135 // enough backing data.
136 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
137 {
138 context->handleError(Error(GL_INVALID_OPERATION,
139 "Vertex buffer is not big enough for the draw call"));
140 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400141 }
142 }
143
144 return true;
145}
146
Geoff Langf607c602016-09-21 11:46:48 -0400147bool ValidReadPixelsFormatType(ValidationContext *context,
148 GLenum framebufferComponentType,
149 GLenum format,
150 GLenum type)
151{
152 switch (framebufferComponentType)
153 {
154 case GL_UNSIGNED_NORMALIZED:
155 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
156 // ReadPixels with BGRA even if the extension is not present
157 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
158 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
159 type == GL_UNSIGNED_BYTE);
160
161 case GL_SIGNED_NORMALIZED:
162 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
163
164 case GL_INT:
165 return (format == GL_RGBA_INTEGER && type == GL_INT);
166
167 case GL_UNSIGNED_INT:
168 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
169
170 case GL_FLOAT:
171 return (format == GL_RGBA && type == GL_FLOAT);
172
173 default:
174 UNREACHABLE();
175 return false;
176 }
177}
178
Geoff Langf41a7152016-09-19 15:11:17 -0400179bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500180{
181 switch (cap)
182 {
Geoff Langf41a7152016-09-19 15:11:17 -0400183 // EXT_multisample_compatibility
184 case GL_MULTISAMPLE_EXT:
185 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
186 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300187
Geoff Langf41a7152016-09-19 15:11:17 -0400188 case GL_CULL_FACE:
189 case GL_POLYGON_OFFSET_FILL:
190 case GL_SAMPLE_ALPHA_TO_COVERAGE:
191 case GL_SAMPLE_COVERAGE:
192 case GL_SCISSOR_TEST:
193 case GL_STENCIL_TEST:
194 case GL_DEPTH_TEST:
195 case GL_BLEND:
196 case GL_DITHER:
197 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500198
Geoff Langf41a7152016-09-19 15:11:17 -0400199 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
200 case GL_RASTERIZER_DISCARD:
201 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500202
Geoff Langf41a7152016-09-19 15:11:17 -0400203 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
204 case GL_DEBUG_OUTPUT:
205 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500206
Geoff Langf41a7152016-09-19 15:11:17 -0400207 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
208 return queryOnly && context->getExtensions().bindGeneratesResource;
209
Geoff Langfeb8c682017-02-13 16:07:35 -0500210 case GL_CLIENT_ARRAYS_ANGLE:
211 return queryOnly && context->getExtensions().clientArrays;
212
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700213 case GL_FRAMEBUFFER_SRGB_EXT:
214 return context->getExtensions().sRGBWriteControl;
215
Geoff Lang3b573612016-10-31 14:08:10 -0400216 case GL_SAMPLE_MASK:
Geoff Lang3b573612016-10-31 14:08:10 -0400217 return context->getClientVersion() >= Version(3, 1);
218
Jamie Madille08a1d32017-03-07 17:24:06 -0500219 case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
220 return queryOnly && context->getExtensions().robustResourceInitialization;
221
Geoff Langf41a7152016-09-19 15:11:17 -0400222 default:
223 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500224 }
225}
226
Geoff Lang62fce5b2016-09-30 10:46:35 -0400227bool ValidateReadPixelsBase(ValidationContext *context,
228 GLint x,
229 GLint y,
230 GLsizei width,
231 GLsizei height,
232 GLenum format,
233 GLenum type,
234 GLsizei bufSize,
235 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -0400236 GLsizei *columns,
237 GLsizei *rows,
Geoff Lang62fce5b2016-09-30 10:46:35 -0400238 GLvoid *pixels)
239{
240 if (length != nullptr)
241 {
242 *length = 0;
243 }
Geoff Lange93daba2017-03-30 13:54:40 -0400244 if (rows != nullptr)
245 {
246 *rows = 0;
247 }
248 if (columns != nullptr)
249 {
250 *columns = 0;
251 }
Geoff Lang62fce5b2016-09-30 10:46:35 -0400252
253 if (width < 0 || height < 0)
254 {
255 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
256 return false;
257 }
258
259 auto readFramebuffer = context->getGLState().getReadFramebuffer();
260
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
Geoff Lang407d4e72017-04-12 14:54:11 -04001823bool ValidateDrawElementsInstancedBase(Context *context,
1824 GLenum mode,
1825 GLsizei count,
1826 GLenum type,
1827 const GLvoid *indices,
1828 GLsizei primcount,
1829 IndexRange *indexRangeOut)
1830{
1831 if (primcount < 0)
1832 {
1833 context->handleError(Error(GL_INVALID_VALUE, "primcount cannot be negative."));
1834 return false;
1835 }
1836
1837 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
1838 {
1839 return false;
1840 }
1841
1842 // No-op zero primitive count
1843 return (primcount > 0);
1844}
1845
1846bool ValidateDrawArraysInstancedBase(Context *context,
1847 GLenum mode,
1848 GLint first,
1849 GLsizei count,
1850 GLsizei primcount)
1851{
1852 if (primcount < 0)
1853 {
1854 context->handleError(Error(GL_INVALID_VALUE, "primcount cannot be negative."));
1855 return false;
1856 }
1857
1858 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
1859 {
1860 return false;
1861 }
1862
1863 // No-op if zero primitive count
1864 return (primcount > 0);
1865}
1866
1867bool ValidateDrawInstancedANGLEAndWebGL(Context *context)
1868{
1869 // Verify there is at least one active attribute with a divisor of zero
1870 const State &state = context->getGLState();
1871
1872 Program *program = state.getProgram();
1873
1874 const auto &attribs = state.getVertexArray()->getVertexAttributes();
1875 const auto &bindings = state.getVertexArray()->getVertexBindings();
1876 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
1877 {
1878 const VertexAttribute &attrib = attribs[attributeIndex];
1879 const VertexBinding &binding = bindings[attrib.bindingIndex];
1880 if (program->isAttribLocationActive(attributeIndex) && binding.divisor == 0)
1881 {
1882 return true;
1883 }
1884 }
1885
1886 context->handleError(
1887 Error(GL_INVALID_OPERATION, "At least one attribute must have a divisor of zero."));
1888 return false;
1889}
1890
Geoff Langf41a7152016-09-19 15:11:17 -04001891} // anonymous namespace
1892
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001893bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001894{
Jamie Madilld7460c72014-01-21 16:38:14 -05001895 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001896 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001897 case GL_TEXTURE_2D:
1898 case GL_TEXTURE_CUBE_MAP:
1899 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001900
He Yunchaoced53ae2016-11-29 15:00:51 +08001901 case GL_TEXTURE_3D:
1902 case GL_TEXTURE_2D_ARRAY:
1903 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001904
He Yunchaoced53ae2016-11-29 15:00:51 +08001905 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001906 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001907
He Yunchaoced53ae2016-11-29 15:00:51 +08001908 default:
1909 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001910 }
Jamie Madill35d15012013-10-07 10:46:37 -04001911}
1912
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001913bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1914{
1915 switch (target)
1916 {
1917 case GL_TEXTURE_2D:
1918 case GL_TEXTURE_CUBE_MAP:
1919 return true;
1920
1921 default:
1922 return false;
1923 }
1924}
1925
1926bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1927{
1928 switch (target)
1929 {
1930 case GL_TEXTURE_3D:
1931 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001932 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001933
1934 default:
1935 return false;
1936 }
1937}
1938
Ian Ewellbda75592016-04-18 17:25:54 -04001939// Most texture GL calls are not compatible with external textures, so we have a separate validation
1940// function for use in the GL calls that do
1941bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1942{
1943 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1944 (context->getExtensions().eglImageExternal ||
1945 context->getExtensions().eglStreamConsumerExternal);
1946}
1947
Shannon Woods4dfed832014-03-17 20:03:39 -04001948// This function differs from ValidTextureTarget in that the target must be
1949// usable as the destination of a 2D operation-- so a cube face is valid, but
1950// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001951// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001952bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001953{
1954 switch (target)
1955 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001956 case GL_TEXTURE_2D:
1957 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1958 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1959 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1960 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1961 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1962 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1963 return true;
1964 default:
1965 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001966 }
1967}
1968
1969bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1970{
1971 switch (target)
1972 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001973 case GL_TEXTURE_3D:
1974 case GL_TEXTURE_2D_ARRAY:
1975 return true;
1976 default:
1977 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001978 }
1979}
1980
He Yunchao11b038b2016-11-22 21:24:04 +08001981bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1982{
1983 switch (target)
1984 {
1985 case GL_TEXTURE_2D:
1986 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1987 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1988 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1989 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1990 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1991 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1992 case GL_TEXTURE_3D:
1993 case GL_TEXTURE_2D_ARRAY:
1994 case GL_TEXTURE_2D_MULTISAMPLE:
1995 return true;
1996 default:
1997 return false;
1998 }
1999}
2000
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002001bool ValidFramebufferTarget(GLenum target)
2002{
He Yunchaoced53ae2016-11-29 15:00:51 +08002003 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
2004 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04002005 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002006
2007 switch (target)
2008 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002009 case GL_FRAMEBUFFER:
2010 return true;
2011 case GL_READ_FRAMEBUFFER:
2012 return true;
2013 case GL_DRAW_FRAMEBUFFER:
2014 return true;
2015 default:
2016 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002017 }
2018}
2019
Jamie Madill29639852016-09-02 15:00:09 -04002020bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05002021{
2022 switch (target)
2023 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002024 case GL_ARRAY_BUFFER:
2025 case GL_ELEMENT_ARRAY_BUFFER:
2026 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05002027
He Yunchaoced53ae2016-11-29 15:00:51 +08002028 case GL_PIXEL_PACK_BUFFER:
2029 case GL_PIXEL_UNPACK_BUFFER:
2030 return (context->getExtensions().pixelBufferObject ||
2031 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04002032
He Yunchaoced53ae2016-11-29 15:00:51 +08002033 case GL_COPY_READ_BUFFER:
2034 case GL_COPY_WRITE_BUFFER:
2035 case GL_TRANSFORM_FEEDBACK_BUFFER:
2036 case GL_UNIFORM_BUFFER:
2037 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05002038
He Yunchaoced53ae2016-11-29 15:00:51 +08002039 case GL_ATOMIC_COUNTER_BUFFER:
2040 case GL_SHADER_STORAGE_BUFFER:
2041 case GL_DRAW_INDIRECT_BUFFER:
2042 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08002043 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04002044
He Yunchaoced53ae2016-11-29 15:00:51 +08002045 default:
2046 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05002047 }
2048}
2049
Jamie Madillc29968b2016-01-20 11:17:23 -05002050bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04002051{
Jamie Madillc29968b2016-01-20 11:17:23 -05002052 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04002053 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04002054 switch (target)
2055 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002056 case GL_TEXTURE_2D:
2057 maxDimension = caps.max2DTextureSize;
2058 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002059 case GL_TEXTURE_CUBE_MAP:
2060 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2061 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2062 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2063 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2064 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2065 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2066 maxDimension = caps.maxCubeMapTextureSize;
2067 break;
2068 case GL_TEXTURE_3D:
2069 maxDimension = caps.max3DTextureSize;
2070 break;
2071 case GL_TEXTURE_2D_ARRAY:
2072 maxDimension = caps.max2DTextureSize;
2073 break;
He Yunchao11b038b2016-11-22 21:24:04 +08002074 case GL_TEXTURE_2D_MULTISAMPLE:
2075 maxDimension = caps.max2DTextureSize;
2076 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002077 default:
2078 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04002079 }
2080
Cooper Partin4d61f7e2015-08-12 10:56:50 -07002081 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04002082}
2083
Geoff Langcc507aa2016-12-12 10:09:52 -05002084bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07002085 GLenum target,
2086 GLint level,
2087 GLsizei width,
2088 GLsizei height,
2089 GLsizei depth,
2090 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04002091{
2092 if (level < 0 || width < 0 || height < 0 || depth < 0)
2093 {
2094 return false;
2095 }
2096
Austin Kinross08528e12015-10-07 16:24:40 -07002097 // TexSubImage parameters can be NPOT without textureNPOT extension,
2098 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05002099 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05002100 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05002101 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04002102 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04002103 {
2104 return false;
2105 }
2106
2107 if (!ValidMipLevel(context, target, level))
2108 {
2109 return false;
2110 }
2111
2112 return true;
2113}
2114
Geoff Lang0d8b7242015-09-09 14:56:53 -04002115bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
2116{
2117 // List of compressed format that require that the texture size is smaller than or a multiple of
2118 // the compressed block size.
2119 switch (internalFormat)
2120 {
2121 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
2122 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
2123 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
2124 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08002125 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08002126 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
2127 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
2128 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
2129 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
2130 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
2131 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04002132 return true;
2133
2134 default:
2135 return false;
2136 }
2137}
2138
Jamie Madillc29968b2016-01-20 11:17:23 -05002139bool ValidCompressedImageSize(const ValidationContext *context,
2140 GLenum internalFormat,
Geoff Lang44ff5a72017-02-03 15:15:43 -05002141 GLint xoffset,
2142 GLint yoffset,
Jamie Madillc29968b2016-01-20 11:17:23 -05002143 GLsizei width,
2144 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04002145{
Geoff Langca271392017-04-05 12:30:00 -04002146 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04002147 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04002148 {
2149 return false;
2150 }
2151
Geoff Lang44ff5a72017-02-03 15:15:43 -05002152 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04002153 {
2154 return false;
2155 }
2156
Geoff Lang0d8b7242015-09-09 14:56:53 -04002157 if (CompressedTextureFormatRequiresExactSize(internalFormat))
2158 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05002159 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
2160 yoffset % formatInfo.compressedBlockHeight != 0 ||
2161 (static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
Geoff Lang0d8b7242015-09-09 14:56:53 -04002162 width % formatInfo.compressedBlockWidth != 0) ||
2163 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
2164 height % formatInfo.compressedBlockHeight != 0))
2165 {
2166 return false;
2167 }
2168 }
2169
Geoff Langd4f180b2013-09-24 13:57:44 -04002170 return true;
2171}
2172
Geoff Langff5b2d52016-09-07 11:32:23 -04002173bool ValidImageDataSize(ValidationContext *context,
2174 GLenum textureTarget,
2175 GLsizei width,
2176 GLsizei height,
2177 GLsizei depth,
2178 GLenum internalFormat,
2179 GLenum type,
2180 const GLvoid *pixels,
2181 GLsizei imageSize)
2182{
2183 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
2184 if (pixelUnpackBuffer == nullptr && imageSize < 0)
2185 {
2186 // Checks are not required
2187 return true;
2188 }
2189
2190 // ...the data would be unpacked from the buffer object such that the memory reads required
2191 // would exceed the data store size.
Geoff Langca271392017-04-05 12:30:00 -04002192 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
Geoff Langff5b2d52016-09-07 11:32:23 -04002193 const gl::Extents size(width, height, depth);
2194 const auto &unpack = context->getGLState().getUnpackState();
2195
2196 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
2197 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
2198 if (endByteOrErr.isError())
2199 {
2200 context->handleError(endByteOrErr.getError());
2201 return false;
2202 }
2203
2204 GLuint endByte = endByteOrErr.getResult();
2205
2206 if (pixelUnpackBuffer)
2207 {
2208 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
2209 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
2210 checkedEndByte += checkedOffset;
2211
2212 if (!checkedEndByte.IsValid() ||
2213 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
2214 {
2215 // Overflow past the end of the buffer
2216 context->handleError(Error(GL_INVALID_OPERATION));
2217 return false;
2218 }
2219 }
2220 else
2221 {
2222 ASSERT(imageSize >= 0);
2223 if (pixels == nullptr && imageSize != 0)
2224 {
2225 context->handleError(
2226 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04002227 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04002228 }
2229
Geoff Lang3feb3ff2016-10-26 10:57:45 -04002230 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04002231 {
2232 context->handleError(
2233 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
2234 return false;
2235 }
2236 }
2237
2238 return true;
2239}
2240
Geoff Lang37dde692014-01-31 16:34:54 -05002241bool ValidQueryType(const Context *context, GLenum queryType)
2242{
He Yunchaoced53ae2016-11-29 15:00:51 +08002243 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
2244 "GL extension enums not equal.");
2245 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2246 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05002247
2248 switch (queryType)
2249 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002250 case GL_ANY_SAMPLES_PASSED:
2251 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
2252 return true;
2253 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
2254 return (context->getClientMajorVersion() >= 3);
2255 case GL_TIME_ELAPSED_EXT:
2256 return context->getExtensions().disjointTimerQuery;
2257 case GL_COMMANDS_COMPLETED_CHROMIUM:
2258 return context->getExtensions().syncQuery;
2259 default:
2260 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05002261 }
2262}
2263
Geoff Lang2d62ab72017-03-23 16:54:40 -04002264bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
2265 GLenum type,
2266 GLboolean normalized,
2267 GLsizei stride,
2268 const GLvoid *ptr,
2269 bool pureInteger)
2270{
2271 ASSERT(context->getExtensions().webglCompatibility);
2272
2273 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
2274 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
2275 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
2276 // parameter exceeds 255.
2277 constexpr GLsizei kMaxWebGLStride = 255;
2278 if (stride > kMaxWebGLStride)
2279 {
2280 context->handleError(
2281 Error(GL_INVALID_VALUE, "Stride is over the maximum stride allowed by WebGL."));
2282 return false;
2283 }
2284
2285 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
2286 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
2287 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
2288 // or an INVALID_OPERATION error is generated.
2289 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
2290 size_t typeSize = GetVertexFormatTypeSize(internalType);
2291
2292 ASSERT(isPow2(typeSize) && typeSize > 0);
2293 size_t sizeMask = (typeSize - 1);
2294 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
2295 {
2296 context->handleError(
2297 Error(GL_INVALID_OPERATION, "Offset is not a multiple of the type size."));
2298 return false;
2299 }
2300
2301 if ((stride & sizeMask) != 0)
2302 {
2303 context->handleError(
2304 Error(GL_INVALID_OPERATION, "Stride is not a multiple of the type size."));
2305 return false;
2306 }
2307
2308 return true;
2309}
2310
Jamie Madillef300b12016-10-07 15:12:09 -04002311Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05002312{
He Yunchaoced53ae2016-11-29 15:00:51 +08002313 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
2314 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
2315 // or program object and INVALID_OPERATION if the provided name identifies an object
2316 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05002317
Dian Xiang769769a2015-09-09 15:20:08 -07002318 Program *validProgram = context->getProgram(id);
2319
2320 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05002321 {
Dian Xiang769769a2015-09-09 15:20:08 -07002322 if (context->getShader(id))
2323 {
Jamie Madill437fa652016-05-03 15:13:24 -04002324 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07002325 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
2326 }
2327 else
2328 {
Jamie Madill437fa652016-05-03 15:13:24 -04002329 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07002330 }
Geoff Lang48dcae72014-02-05 16:28:24 -05002331 }
Dian Xiang769769a2015-09-09 15:20:08 -07002332
2333 return validProgram;
2334}
2335
Jamie Madillef300b12016-10-07 15:12:09 -04002336Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07002337{
2338 // See ValidProgram for spec details.
2339
2340 Shader *validShader = context->getShader(id);
2341
2342 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05002343 {
Dian Xiang769769a2015-09-09 15:20:08 -07002344 if (context->getProgram(id))
2345 {
Jamie Madill437fa652016-05-03 15:13:24 -04002346 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07002347 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
2348 }
2349 else
2350 {
Jamie Madill437fa652016-05-03 15:13:24 -04002351 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07002352 }
Geoff Lang48dcae72014-02-05 16:28:24 -05002353 }
Dian Xiang769769a2015-09-09 15:20:08 -07002354
2355 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05002356}
2357
Geoff Langb1196682014-07-23 13:47:29 -04002358bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04002359{
2360 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
2361 {
2362 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
2363
Geoff Langaae65a42014-05-26 12:43:44 -04002364 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04002365 {
Jamie Madill437fa652016-05-03 15:13:24 -04002366 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002367 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04002368 }
2369 }
2370 else
2371 {
2372 switch (attachment)
2373 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002374 case GL_DEPTH_ATTACHMENT:
2375 case GL_STENCIL_ATTACHMENT:
2376 break;
Jamie Madillb4472272014-07-03 10:38:55 -04002377
He Yunchaoced53ae2016-11-29 15:00:51 +08002378 case GL_DEPTH_STENCIL_ATTACHMENT:
2379 if (!context->getExtensions().webglCompatibility &&
2380 context->getClientMajorVersion() < 3)
2381 {
2382 context->handleError(Error(GL_INVALID_ENUM));
2383 return false;
2384 }
2385 break;
Jamie Madillb4472272014-07-03 10:38:55 -04002386
He Yunchaoced53ae2016-11-29 15:00:51 +08002387 default:
2388 context->handleError(Error(GL_INVALID_ENUM));
2389 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04002390 }
2391 }
2392
2393 return true;
2394}
2395
Jamie Madille8fb6402017-02-14 17:56:40 -05002396bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08002397 GLenum target,
2398 GLsizei samples,
2399 GLenum internalformat,
2400 GLsizei width,
2401 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002402{
2403 switch (target)
2404 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002405 case GL_RENDERBUFFER:
2406 break;
2407 default:
2408 context->handleError(Error(GL_INVALID_ENUM));
2409 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002410 }
2411
2412 if (width < 0 || height < 0 || samples < 0)
2413 {
Jamie Madill437fa652016-05-03 15:13:24 -04002414 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002415 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002416 }
2417
Jamie Madill4e0e6f82017-02-17 11:06:03 -05002418 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
2419 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
2420
2421 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04002422 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002423 {
Jamie Madill437fa652016-05-03 15:13:24 -04002424 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002425 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002426 }
2427
2428 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
2429 // 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 -08002430 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04002431 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
2432 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002433 {
Jamie Madill437fa652016-05-03 15:13:24 -04002434 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002435 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002436 }
2437
Geoff Langaae65a42014-05-26 12:43:44 -04002438 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002439 {
Jamie Madill437fa652016-05-03 15:13:24 -04002440 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002441 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002442 }
2443
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002444 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002445 if (handle == 0)
2446 {
Jamie Madill437fa652016-05-03 15:13:24 -04002447 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002448 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002449 }
2450
2451 return true;
2452}
2453
He Yunchaoced53ae2016-11-29 15:00:51 +08002454bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
2455 GLenum target,
2456 GLenum attachment,
2457 GLenum renderbuffertarget,
2458 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002459{
Shannon Woods1da3cf62014-06-27 15:32:23 -04002460 if (!ValidFramebufferTarget(target))
2461 {
Jamie Madill437fa652016-05-03 15:13:24 -04002462 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002463 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04002464 }
2465
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002466 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002467
Jamie Madill84115c92015-04-23 15:00:07 -04002468 ASSERT(framebuffer);
2469 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002470 {
Jamie Madill437fa652016-05-03 15:13:24 -04002471 context->handleError(
2472 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002473 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002474 }
2475
Jamie Madillb4472272014-07-03 10:38:55 -04002476 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002477 {
Jamie Madillb4472272014-07-03 10:38:55 -04002478 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002479 }
2480
Jamie Madillab9d82c2014-01-21 16:38:14 -05002481 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2482 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2483 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2484 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2485 if (renderbuffer != 0)
2486 {
2487 if (!context->getRenderbuffer(renderbuffer))
2488 {
Jamie Madill437fa652016-05-03 15:13:24 -04002489 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002490 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05002491 }
2492 }
2493
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002494 return true;
2495}
2496
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002497bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002498 GLint srcX0,
2499 GLint srcY0,
2500 GLint srcX1,
2501 GLint srcY1,
2502 GLint dstX0,
2503 GLint dstY0,
2504 GLint dstX1,
2505 GLint dstY1,
2506 GLbitfield mask,
2507 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002508{
2509 switch (filter)
2510 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002511 case GL_NEAREST:
2512 break;
2513 case GL_LINEAR:
2514 break;
2515 default:
2516 context->handleError(Error(GL_INVALID_ENUM));
2517 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002518 }
2519
2520 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
2521 {
Jamie Madill437fa652016-05-03 15:13:24 -04002522 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002523 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002524 }
2525
2526 if (mask == 0)
2527 {
2528 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
2529 // buffers are copied.
2530 return false;
2531 }
2532
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002533 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
2534 // color buffer, leaving only nearest being unfiltered from above
2535 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
2536 {
Jamie Madill437fa652016-05-03 15:13:24 -04002537 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002538 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002539 }
2540
Jamie Madill51f40ec2016-06-15 14:06:00 -04002541 const auto &glState = context->getGLState();
2542 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2543 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05002544
2545 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002546 {
Jamie Madill437fa652016-05-03 15:13:24 -04002547 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002548 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002549 }
2550
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002551 if (readFramebuffer->id() == drawFramebuffer->id())
2552 {
2553 context->handleError(Error(GL_INVALID_OPERATION));
2554 return false;
2555 }
2556
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002557 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002558 {
Jamie Madill437fa652016-05-03 15:13:24 -04002559 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002560 return false;
2561 }
2562
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002563 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002564 {
Jamie Madill437fa652016-05-03 15:13:24 -04002565 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002566 return false;
2567 }
2568
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002569 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002570 {
Jamie Madill437fa652016-05-03 15:13:24 -04002571 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002572 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002573 }
2574
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002575 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2576
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002577 if (mask & GL_COLOR_BUFFER_BIT)
2578 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002579 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002580 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002581
He Yunchao66a41a22016-12-15 16:45:05 +08002582 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002583 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002584 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002585
Geoff Langa15472a2015-08-11 11:48:03 -04002586 for (size_t drawbufferIdx = 0;
2587 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002588 {
Geoff Langa15472a2015-08-11 11:48:03 -04002589 const FramebufferAttachment *attachment =
2590 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2591 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002592 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002593 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002594
Geoff Langb2f3d052013-08-13 12:49:27 -04002595 // The GL ES 3.0.2 spec (pg 193) states that:
2596 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002597 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2598 // as well
2599 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2600 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002601 // Changes with EXT_color_buffer_float:
2602 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002603 GLenum readComponentType = readFormat.info->componentType;
2604 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002605 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002606 readComponentType == GL_SIGNED_NORMALIZED);
2607 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2608 drawComponentType == GL_SIGNED_NORMALIZED);
2609
2610 if (extensions.colorBufferFloat)
2611 {
2612 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2613 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2614
2615 if (readFixedOrFloat != drawFixedOrFloat)
2616 {
Jamie Madill437fa652016-05-03 15:13:24 -04002617 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002618 "If the read buffer contains fixed-point or "
2619 "floating-point values, the draw buffer "
2620 "must as well."));
2621 return false;
2622 }
2623 }
2624 else if (readFixedPoint != drawFixedPoint)
2625 {
Jamie Madill437fa652016-05-03 15:13:24 -04002626 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002627 "If the read buffer contains fixed-point "
2628 "values, the draw buffer must as well."));
2629 return false;
2630 }
2631
2632 if (readComponentType == GL_UNSIGNED_INT &&
2633 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002634 {
Jamie Madill437fa652016-05-03 15:13:24 -04002635 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002636 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002637 }
2638
Jamie Madill6163c752015-12-07 16:32:59 -05002639 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002640 {
Jamie Madill437fa652016-05-03 15:13:24 -04002641 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002642 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002643 }
2644
Jamie Madilla3944d42016-07-22 22:13:26 -04002645 if (readColorBuffer->getSamples() > 0 &&
2646 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002647 {
Jamie Madill437fa652016-05-03 15:13:24 -04002648 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002649 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002650 }
Geoff Lange4915782017-04-12 15:19:07 -04002651
2652 if (context->getExtensions().webglCompatibility &&
2653 *readColorBuffer == *attachment)
2654 {
2655 context->handleError(
2656 Error(GL_INVALID_OPERATION,
2657 "Read and write color attachments cannot be the same image."));
2658 return false;
2659 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002660 }
2661 }
2662
Jamie Madilla3944d42016-07-22 22:13:26 -04002663 if ((readFormat.info->componentType == GL_INT ||
2664 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2665 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002666 {
Jamie Madill437fa652016-05-03 15:13:24 -04002667 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002668 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002669 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002670 }
He Yunchao66a41a22016-12-15 16:45:05 +08002671 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2672 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2673 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2674 // situation is an application error that would lead to a crash in ANGLE.
2675 else if (drawFramebuffer->hasEnabledDrawBuffer())
2676 {
2677 context->handleError(Error(
2678 GL_INVALID_OPERATION,
2679 "Attempt to read from a missing color attachment of a complete framebuffer."));
2680 return false;
2681 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002682 }
2683
He Yunchaoced53ae2016-11-29 15:00:51 +08002684 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002685 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2686 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002687 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002688 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002689 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002690 const gl::FramebufferAttachment *readBuffer =
2691 readFramebuffer->getAttachment(attachments[i]);
2692 const gl::FramebufferAttachment *drawBuffer =
2693 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002694
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002695 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002696 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002697 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
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 Lange8ebe7f2013-08-05 15:03:13 -04002702
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002703 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002704 {
Jamie Madill437fa652016-05-03 15:13:24 -04002705 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002706 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002707 }
Geoff Lange4915782017-04-12 15:19:07 -04002708
2709 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
2710 {
2711 context->handleError(Error(
2712 GL_INVALID_OPERATION,
2713 "Read and write depth stencil attachments cannot be the same image."));
2714 return false;
2715 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002716 }
He Yunchao66a41a22016-12-15 16:45:05 +08002717 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2718 else if (drawBuffer)
2719 {
2720 context->handleError(Error(GL_INVALID_OPERATION,
2721 "Attempt to read from a missing depth/stencil "
2722 "attachment of a complete framebuffer."));
2723 return false;
2724 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002725 }
2726 }
2727
2728 return true;
2729}
2730
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002731bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002732 GLint x,
2733 GLint y,
2734 GLsizei width,
2735 GLsizei height,
2736 GLenum format,
2737 GLenum type,
2738 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002739{
Geoff Lange93daba2017-03-30 13:54:40 -04002740 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
2741 nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04002742}
2743
2744bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2745 GLint x,
2746 GLint y,
2747 GLsizei width,
2748 GLsizei height,
2749 GLenum format,
2750 GLenum type,
2751 GLsizei bufSize,
2752 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04002753 GLsizei *columns,
2754 GLsizei *rows,
Geoff Lang62fce5b2016-09-30 10:46:35 -04002755 GLvoid *pixels)
2756{
2757 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002758 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002759 return false;
2760 }
2761
Geoff Lang62fce5b2016-09-30 10:46:35 -04002762 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04002763 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002764 {
Geoff Langb1196682014-07-23 13:47:29 -04002765 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002766 }
2767
Geoff Lang62fce5b2016-09-30 10:46:35 -04002768 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002769 {
Geoff Langb1196682014-07-23 13:47:29 -04002770 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002771 }
2772
Jamie Madillc29968b2016-01-20 11:17:23 -05002773 return true;
2774}
2775
2776bool ValidateReadnPixelsEXT(Context *context,
2777 GLint x,
2778 GLint y,
2779 GLsizei width,
2780 GLsizei height,
2781 GLenum format,
2782 GLenum type,
2783 GLsizei bufSize,
2784 GLvoid *pixels)
2785{
2786 if (bufSize < 0)
2787 {
Jamie Madill437fa652016-05-03 15:13:24 -04002788 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002789 return false;
2790 }
2791
Geoff Lang62fce5b2016-09-30 10:46:35 -04002792 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04002793 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04002794}
Jamie Madill26e91952014-03-05 15:01:27 -05002795
Geoff Lang62fce5b2016-09-30 10:46:35 -04002796bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2797 GLint x,
2798 GLint y,
2799 GLsizei width,
2800 GLsizei height,
2801 GLenum format,
2802 GLenum type,
2803 GLsizei bufSize,
2804 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04002805 GLsizei *columns,
2806 GLsizei *rows,
Geoff Lang62fce5b2016-09-30 10:46:35 -04002807 GLvoid *data)
2808{
2809 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002810 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002811 return false;
2812 }
2813
Geoff Lange93daba2017-03-30 13:54:40 -04002814 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2815 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002816 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002817 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002818 }
2819
Geoff Lang62fce5b2016-09-30 10:46:35 -04002820 if (!ValidateRobustBufferSize(context, bufSize, *length))
2821 {
2822 return false;
2823 }
2824
2825 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002826}
2827
Olli Etuaho41997e72016-03-10 13:38:39 +02002828bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002829{
2830 if (!context->getExtensions().occlusionQueryBoolean &&
2831 !context->getExtensions().disjointTimerQuery)
2832 {
Jamie Madill437fa652016-05-03 15:13:24 -04002833 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002834 return false;
2835 }
2836
Olli Etuaho41997e72016-03-10 13:38:39 +02002837 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002838}
2839
Olli Etuaho41997e72016-03-10 13:38:39 +02002840bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002841{
2842 if (!context->getExtensions().occlusionQueryBoolean &&
2843 !context->getExtensions().disjointTimerQuery)
2844 {
Jamie Madill437fa652016-05-03 15:13:24 -04002845 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002846 return false;
2847 }
2848
Olli Etuaho41997e72016-03-10 13:38:39 +02002849 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002850}
2851
2852bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002853{
2854 if (!ValidQueryType(context, target))
2855 {
Jamie Madill437fa652016-05-03 15:13:24 -04002856 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002857 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002858 }
2859
2860 if (id == 0)
2861 {
Jamie Madill437fa652016-05-03 15:13:24 -04002862 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002863 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002864 }
2865
2866 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2867 // of zero, if the active query object name for <target> is non-zero (for the
2868 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2869 // the active query for either target is non-zero), if <id> is the name of an
2870 // existing query object whose type does not match <target>, or if <id> is the
2871 // active query object name for any query type, the error INVALID_OPERATION is
2872 // generated.
2873
2874 // Ensure no other queries are active
2875 // NOTE: If other queries than occlusion are supported, we will need to check
2876 // separately that:
2877 // a) The query ID passed is not the current active query for any target/type
2878 // b) There are no active queries for the requested target (and in the case
2879 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2880 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002881
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002882 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002883 {
Jamie Madill437fa652016-05-03 15:13:24 -04002884 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002885 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002886 }
2887
2888 Query *queryObject = context->getQuery(id, true, target);
2889
2890 // check that name was obtained with glGenQueries
2891 if (!queryObject)
2892 {
Jamie Madill437fa652016-05-03 15:13:24 -04002893 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002894 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002895 }
2896
2897 // check for type mismatch
2898 if (queryObject->getType() != target)
2899 {
Jamie Madill437fa652016-05-03 15:13:24 -04002900 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002901 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002902 }
2903
2904 return true;
2905}
2906
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002907bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2908{
2909 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002910 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002911 {
Jamie Madill437fa652016-05-03 15:13:24 -04002912 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002913 return false;
2914 }
2915
2916 return ValidateBeginQueryBase(context, target, id);
2917}
2918
2919bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002920{
2921 if (!ValidQueryType(context, target))
2922 {
Jamie Madill437fa652016-05-03 15:13:24 -04002923 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002924 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002925 }
2926
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002927 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002928
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002929 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002930 {
Jamie Madill437fa652016-05-03 15:13:24 -04002931 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002932 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002933 }
2934
Jamie Madill45c785d2014-05-13 14:09:34 -04002935 return true;
2936}
2937
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002938bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2939{
2940 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002941 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002942 {
Jamie Madill437fa652016-05-03 15:13:24 -04002943 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002944 return false;
2945 }
2946
2947 return ValidateEndQueryBase(context, target);
2948}
2949
2950bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2951{
2952 if (!context->getExtensions().disjointTimerQuery)
2953 {
Jamie Madill437fa652016-05-03 15:13:24 -04002954 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002955 return false;
2956 }
2957
2958 if (target != GL_TIMESTAMP_EXT)
2959 {
Jamie Madill437fa652016-05-03 15:13:24 -04002960 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002961 return false;
2962 }
2963
2964 Query *queryObject = context->getQuery(id, true, target);
2965 if (queryObject == nullptr)
2966 {
Jamie Madill437fa652016-05-03 15:13:24 -04002967 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002968 return false;
2969 }
2970
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002971 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002972 {
Jamie Madill437fa652016-05-03 15:13:24 -04002973 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002974 return false;
2975 }
2976
2977 return true;
2978}
2979
Geoff Lang2186c382016-10-14 10:54:54 -04002980bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002981{
Geoff Lang2186c382016-10-14 10:54:54 -04002982 if (numParams)
2983 {
2984 *numParams = 0;
2985 }
2986
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002987 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2988 {
Jamie Madill437fa652016-05-03 15:13:24 -04002989 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002990 return false;
2991 }
2992
2993 switch (pname)
2994 {
2995 case GL_CURRENT_QUERY_EXT:
2996 if (target == GL_TIMESTAMP_EXT)
2997 {
Jamie Madill437fa652016-05-03 15:13:24 -04002998 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002999 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
3000 return false;
3001 }
3002 break;
3003 case GL_QUERY_COUNTER_BITS_EXT:
3004 if (!context->getExtensions().disjointTimerQuery ||
3005 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
3006 {
Jamie Madill437fa652016-05-03 15:13:24 -04003007 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003008 return false;
3009 }
3010 break;
3011 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003012 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003013 return false;
3014 }
3015
Geoff Lang2186c382016-10-14 10:54:54 -04003016 if (numParams)
3017 {
3018 // All queries return only one value
3019 *numParams = 1;
3020 }
3021
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003022 return true;
3023}
3024
3025bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
3026{
3027 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04003028 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003029 {
Jamie Madill437fa652016-05-03 15:13:24 -04003030 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003031 return false;
3032 }
3033
Geoff Lang2186c382016-10-14 10:54:54 -04003034 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003035}
3036
Geoff Lang2186c382016-10-14 10:54:54 -04003037bool ValidateGetQueryivRobustANGLE(Context *context,
3038 GLenum target,
3039 GLenum pname,
3040 GLsizei bufSize,
3041 GLsizei *length,
3042 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003043{
Geoff Lang2186c382016-10-14 10:54:54 -04003044 if (!ValidateRobustEntryPoint(context, bufSize))
3045 {
3046 return false;
3047 }
3048
3049 if (!ValidateGetQueryivBase(context, target, pname, length))
3050 {
3051 return false;
3052 }
3053
3054 if (!ValidateRobustBufferSize(context, bufSize, *length))
3055 {
3056 return false;
3057 }
3058
3059 return true;
3060}
3061
3062bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
3063{
3064 if (numParams)
3065 {
3066 *numParams = 0;
3067 }
3068
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003069 Query *queryObject = context->getQuery(id, false, GL_NONE);
3070
3071 if (!queryObject)
3072 {
Jamie Madill437fa652016-05-03 15:13:24 -04003073 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003074 return false;
3075 }
3076
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003077 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003078 {
Jamie Madill437fa652016-05-03 15:13:24 -04003079 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003080 return false;
3081 }
3082
3083 switch (pname)
3084 {
3085 case GL_QUERY_RESULT_EXT:
3086 case GL_QUERY_RESULT_AVAILABLE_EXT:
3087 break;
3088
3089 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003090 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003091 return false;
3092 }
3093
Geoff Lang2186c382016-10-14 10:54:54 -04003094 if (numParams)
3095 {
3096 *numParams = 1;
3097 }
3098
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003099 return true;
3100}
3101
3102bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
3103{
3104 if (!context->getExtensions().disjointTimerQuery)
3105 {
Jamie Madill437fa652016-05-03 15:13:24 -04003106 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003107 return false;
3108 }
Geoff Lang2186c382016-10-14 10:54:54 -04003109 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
3110}
3111
3112bool ValidateGetQueryObjectivRobustANGLE(Context *context,
3113 GLuint id,
3114 GLenum pname,
3115 GLsizei bufSize,
3116 GLsizei *length,
3117 GLint *params)
3118{
3119 if (!context->getExtensions().disjointTimerQuery)
3120 {
3121 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
3122 return false;
3123 }
3124
3125 if (!ValidateRobustEntryPoint(context, bufSize))
3126 {
3127 return false;
3128 }
3129
3130 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
3131 {
3132 return false;
3133 }
3134
3135 if (!ValidateRobustBufferSize(context, bufSize, *length))
3136 {
3137 return false;
3138 }
3139
3140 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003141}
3142
3143bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
3144{
3145 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04003146 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003147 {
Jamie Madill437fa652016-05-03 15:13:24 -04003148 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003149 return false;
3150 }
Geoff Lang2186c382016-10-14 10:54:54 -04003151 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
3152}
3153
3154bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
3155 GLuint id,
3156 GLenum pname,
3157 GLsizei bufSize,
3158 GLsizei *length,
3159 GLuint *params)
3160{
3161 if (!context->getExtensions().disjointTimerQuery &&
3162 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
3163 {
3164 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
3165 return false;
3166 }
3167
3168 if (!ValidateRobustEntryPoint(context, bufSize))
3169 {
3170 return false;
3171 }
3172
3173 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
3174 {
3175 return false;
3176 }
3177
3178 if (!ValidateRobustBufferSize(context, bufSize, *length))
3179 {
3180 return false;
3181 }
3182
3183 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003184}
3185
3186bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
3187{
3188 if (!context->getExtensions().disjointTimerQuery)
3189 {
Jamie Madill437fa652016-05-03 15:13:24 -04003190 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003191 return false;
3192 }
Geoff Lang2186c382016-10-14 10:54:54 -04003193 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
3194}
3195
3196bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
3197 GLuint id,
3198 GLenum pname,
3199 GLsizei bufSize,
3200 GLsizei *length,
3201 GLint64 *params)
3202{
3203 if (!context->getExtensions().disjointTimerQuery)
3204 {
3205 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
3206 return false;
3207 }
3208
3209 if (!ValidateRobustEntryPoint(context, bufSize))
3210 {
3211 return false;
3212 }
3213
3214 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
3215 {
3216 return false;
3217 }
3218
3219 if (!ValidateRobustBufferSize(context, bufSize, *length))
3220 {
3221 return false;
3222 }
3223
3224 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003225}
3226
3227bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
3228{
3229 if (!context->getExtensions().disjointTimerQuery)
3230 {
Jamie Madill437fa652016-05-03 15:13:24 -04003231 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003232 return false;
3233 }
Geoff Lang2186c382016-10-14 10:54:54 -04003234 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
3235}
3236
3237bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
3238 GLuint id,
3239 GLenum pname,
3240 GLsizei bufSize,
3241 GLsizei *length,
3242 GLuint64 *params)
3243{
3244 if (!context->getExtensions().disjointTimerQuery)
3245 {
3246 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
3247 return false;
3248 }
3249
3250 if (!ValidateRobustEntryPoint(context, bufSize))
3251 {
3252 return false;
3253 }
3254
3255 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
3256 {
3257 return false;
3258 }
3259
3260 if (!ValidateRobustBufferSize(context, bufSize, *length))
3261 {
3262 return false;
3263 }
3264
3265 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003266}
3267
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003268bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003269 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003270 GLuint program,
3271 GLint location,
3272 GLsizei count)
3273{
3274 // Check for ES31 program uniform entry points
3275 if (context->getClientVersion() < Version(3, 1))
3276 {
3277 context->handleError(Error(GL_INVALID_OPERATION));
3278 return false;
3279 }
3280
3281 const LinkedUniform *uniform = nullptr;
3282 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003283 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3284 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003285}
3286
Frank Henigmana98a6472017-02-02 21:38:32 -05003287bool ValidateProgramUniform1iv(gl::Context *context,
3288 GLuint program,
3289 GLint location,
3290 GLsizei count,
3291 const GLint *value)
3292{
3293 // Check for ES31 program uniform entry points
3294 if (context->getClientVersion() < Version(3, 1))
3295 {
3296 context->handleError(Error(GL_INVALID_OPERATION));
3297 return false;
3298 }
3299
3300 const LinkedUniform *uniform = nullptr;
3301 gl::Program *programObject = GetValidProgram(context, program);
3302 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3303 ValidateUniform1ivValue(context, uniform->type, count, value);
3304}
3305
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003306bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003307 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003308 GLuint program,
3309 GLint location,
3310 GLsizei count,
3311 GLboolean transpose)
3312{
3313 // Check for ES31 program uniform entry points
3314 if (context->getClientVersion() < Version(3, 1))
3315 {
3316 context->handleError(Error(GL_INVALID_OPERATION));
3317 return false;
3318 }
3319
3320 const LinkedUniform *uniform = nullptr;
3321 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003322 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3323 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003324}
3325
Jamie Madillc1d770e2017-04-13 17:31:24 -04003326bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04003327{
3328 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003329 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04003330 {
Jamie Madill437fa652016-05-03 15:13:24 -04003331 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003332 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04003333 }
3334
Jamie Madill62d31cb2015-09-11 13:25:51 -04003335 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003336 gl::Program *programObject = context->getGLState().getProgram();
3337 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3338 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04003339}
3340
Frank Henigmana98a6472017-02-02 21:38:32 -05003341bool ValidateUniform1iv(gl::Context *context, GLint location, GLsizei count, const GLint *value)
3342{
3343 const LinkedUniform *uniform = nullptr;
3344 gl::Program *programObject = context->getGLState().getProgram();
3345 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3346 ValidateUniform1ivValue(context, uniform->type, count, value);
3347}
3348
Jamie Madillc1d770e2017-04-13 17:31:24 -04003349bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003350 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08003351 GLint location,
3352 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04003353 GLboolean transpose)
3354{
3355 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003356 int rows = VariableRowCount(valueType);
3357 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03003358 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04003359 {
Jamie Madill437fa652016-05-03 15:13:24 -04003360 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003361 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04003362 }
3363
Martin Radev1be913c2016-07-11 17:59:16 +03003364 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04003365 {
Jamie Madill437fa652016-05-03 15:13:24 -04003366 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003367 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04003368 }
3369
Jamie Madill62d31cb2015-09-11 13:25:51 -04003370 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003371 gl::Program *programObject = context->getGLState().getProgram();
3372 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3373 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04003374}
3375
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003376bool ValidateStateQuery(ValidationContext *context,
3377 GLenum pname,
3378 GLenum *nativeType,
3379 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04003380{
3381 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
3382 {
Jamie Madill437fa652016-05-03 15:13:24 -04003383 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003384 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003385 }
3386
Jamie Madill0af26e12015-03-05 19:54:33 -05003387 const Caps &caps = context->getCaps();
3388
Jamie Madill893ab082014-05-16 16:56:10 -04003389 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
3390 {
3391 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
3392
Jamie Madill0af26e12015-03-05 19:54:33 -05003393 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04003394 {
Jamie Madill437fa652016-05-03 15:13:24 -04003395 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003396 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003397 }
3398 }
3399
3400 switch (pname)
3401 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003402 case GL_TEXTURE_BINDING_2D:
3403 case GL_TEXTURE_BINDING_CUBE_MAP:
3404 case GL_TEXTURE_BINDING_3D:
3405 case GL_TEXTURE_BINDING_2D_ARRAY:
3406 break;
3407 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3408 if (!context->getExtensions().eglStreamConsumerExternal &&
3409 !context->getExtensions().eglImageExternal)
3410 {
3411 context->handleError(Error(GL_INVALID_ENUM,
3412 "Neither NV_EGL_stream_consumer_external nor "
3413 "GL_OES_EGL_image_external extensions enabled"));
3414 return false;
3415 }
3416 break;
Jamie Madill893ab082014-05-16 16:56:10 -04003417
He Yunchaoced53ae2016-11-29 15:00:51 +08003418 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3419 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04003420 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04003421 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
3422 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04003423 {
Jamie Madill437fa652016-05-03 15:13:24 -04003424 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003425 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003426 }
3427
Jamie Madill51f40ec2016-06-15 14:06:00 -04003428 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
3429 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03003430
3431 if (framebuffer->getReadBufferState() == GL_NONE)
3432 {
3433 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3434 return false;
3435 }
3436
Jamie Madillb6bda4a2015-04-20 12:53:26 -04003437 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04003438 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04003439 {
Jamie Madill437fa652016-05-03 15:13:24 -04003440 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003441 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003442 }
3443 }
3444 break;
3445
He Yunchaoced53ae2016-11-29 15:00:51 +08003446 default:
3447 break;
Jamie Madill893ab082014-05-16 16:56:10 -04003448 }
3449
3450 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04003451 if (*numParams == 0)
3452 {
3453 return false;
3454 }
3455
3456 return true;
3457}
3458
3459bool ValidateRobustStateQuery(ValidationContext *context,
3460 GLenum pname,
3461 GLsizei bufSize,
3462 GLenum *nativeType,
3463 unsigned int *numParams)
3464{
3465 if (!ValidateRobustEntryPoint(context, bufSize))
3466 {
3467 return false;
3468 }
3469
3470 if (!ValidateStateQuery(context, pname, nativeType, numParams))
3471 {
3472 return false;
3473 }
3474
3475 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04003476 {
3477 return false;
3478 }
3479
3480 return true;
3481}
3482
Jamie Madillc29968b2016-01-20 11:17:23 -05003483bool ValidateCopyTexImageParametersBase(ValidationContext *context,
3484 GLenum target,
3485 GLint level,
3486 GLenum internalformat,
3487 bool isSubImage,
3488 GLint xoffset,
3489 GLint yoffset,
3490 GLint zoffset,
3491 GLint x,
3492 GLint y,
3493 GLsizei width,
3494 GLsizei height,
3495 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04003496 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04003497{
Jamie Madill560a8d82014-05-21 13:06:20 -04003498 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
3499 {
Jamie Madill437fa652016-05-03 15:13:24 -04003500 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003501 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003502 }
3503
He Yunchaoced53ae2016-11-29 15:00:51 +08003504 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3505 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04003506 {
Jamie Madill437fa652016-05-03 15:13:24 -04003507 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003508 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003509 }
3510
3511 if (border != 0)
3512 {
Jamie Madill437fa652016-05-03 15:13:24 -04003513 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003514 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003515 }
3516
3517 if (!ValidMipLevel(context, target, level))
3518 {
Jamie Madill437fa652016-05-03 15:13:24 -04003519 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003520 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003521 }
3522
Jamie Madill51f40ec2016-06-15 14:06:00 -04003523 const auto &state = context->getGLState();
3524 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04003525 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003526 {
Jamie Madill437fa652016-05-03 15:13:24 -04003527 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003528 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003529 }
3530
Jamie Madilldd43e6c2017-03-24 14:18:49 -04003531 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003532 {
Jamie Madill437fa652016-05-03 15:13:24 -04003533 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003534 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003535 }
3536
Martin Radev138064f2016-07-15 12:03:41 +03003537 if (readFramebuffer->getReadBufferState() == GL_NONE)
3538 {
3539 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3540 return false;
3541 }
3542
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003543 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3544 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003545 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003546 // situation is an application error that would lead to a crash in ANGLE.
3547 if (readFramebuffer->getReadColorbuffer() == nullptr)
3548 {
3549 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3550 return false;
3551 }
3552
Geoff Langaae65a42014-05-26 12:43:44 -04003553 const gl::Caps &caps = context->getCaps();
3554
Geoff Langaae65a42014-05-26 12:43:44 -04003555 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003556 switch (target)
3557 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003558 case GL_TEXTURE_2D:
3559 maxDimension = caps.max2DTextureSize;
3560 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003561
He Yunchaoced53ae2016-11-29 15:00:51 +08003562 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3563 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3564 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3565 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3566 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3567 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3568 maxDimension = caps.maxCubeMapTextureSize;
3569 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003570
He Yunchaoced53ae2016-11-29 15:00:51 +08003571 case GL_TEXTURE_2D_ARRAY:
3572 maxDimension = caps.max2DTextureSize;
3573 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003574
He Yunchaoced53ae2016-11-29 15:00:51 +08003575 case GL_TEXTURE_3D:
3576 maxDimension = caps.max3DTextureSize;
3577 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003578
He Yunchaoced53ae2016-11-29 15:00:51 +08003579 default:
3580 context->handleError(Error(GL_INVALID_ENUM));
3581 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003582 }
3583
Jamie Madillc29968b2016-01-20 11:17:23 -05003584 gl::Texture *texture =
3585 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003586 if (!texture)
3587 {
Jamie Madill437fa652016-05-03 15:13:24 -04003588 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003589 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003590 }
3591
Geoff Lang69cce582015-09-17 13:20:36 -04003592 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003593 {
Jamie Madill437fa652016-05-03 15:13:24 -04003594 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003595 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003596 }
3597
Geoff Langca271392017-04-05 12:30:00 -04003598 const gl::InternalFormat &formatInfo =
3599 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04003600
3601 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003602 {
Jamie Madill437fa652016-05-03 15:13:24 -04003603 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003604 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003605 }
3606
Geoff Lang44ff5a72017-02-03 15:15:43 -05003607 if (formatInfo.compressed &&
3608 !ValidCompressedImageSize(context, internalformat, xoffset, yoffset, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003609 {
Jamie Madill437fa652016-05-03 15:13:24 -04003610 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003611 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003612 }
3613
3614 if (isSubImage)
3615 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003616 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3617 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3618 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003619 {
Jamie Madill437fa652016-05-03 15:13:24 -04003620 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003621 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003622 }
3623 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003624 else
3625 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003626 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003627 {
Jamie Madill437fa652016-05-03 15:13:24 -04003628 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003629 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003630 }
3631
Geoff Langeb66a6e2016-10-31 13:06:12 -04003632 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003633 {
Jamie Madill437fa652016-05-03 15:13:24 -04003634 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003635 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003636 }
3637
3638 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003639 if (static_cast<int>(width) > maxLevelDimension ||
3640 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003641 {
Jamie Madill437fa652016-05-03 15:13:24 -04003642 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003643 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003644 }
3645 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003646
Jamie Madill0c8abca2016-07-22 20:21:26 -04003647 if (textureFormatOut)
3648 {
3649 *textureFormatOut = texture->getFormat(target, level);
3650 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003651
3652 // Detect texture copying feedback loops for WebGL.
3653 if (context->getExtensions().webglCompatibility)
3654 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05003655 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05003656 {
3657 context->handleError(Error(GL_INVALID_OPERATION,
3658 "Texture copying feedback loop formed between Framebuffer "
3659 "and specified Texture level."));
3660 return false;
3661 }
3662 }
3663
Jamie Madill560a8d82014-05-21 13:06:20 -04003664 return true;
3665}
3666
Jiajia Qind9671222016-11-29 16:30:31 +08003667bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003668{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003669 switch (mode)
3670 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003671 case GL_POINTS:
3672 case GL_LINES:
3673 case GL_LINE_LOOP:
3674 case GL_LINE_STRIP:
3675 case GL_TRIANGLES:
3676 case GL_TRIANGLE_STRIP:
3677 case GL_TRIANGLE_FAN:
3678 break;
3679 default:
3680 context->handleError(Error(GL_INVALID_ENUM));
3681 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003682 }
3683
Jamie Madill250d33f2014-06-06 17:09:03 -04003684 if (count < 0)
3685 {
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 Madill250d33f2014-06-06 17:09:03 -04003688 }
3689
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003690 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003691
Jamie Madill250d33f2014-06-06 17:09:03 -04003692 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003693 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003694 {
Jamie Madill437fa652016-05-03 15:13:24 -04003695 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003696 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003697 }
3698
Jamie Madillcbcde722017-01-06 14:50:00 -05003699 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3700 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003701 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003702 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3703 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003704 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003705 const FramebufferAttachment *dsAttachment =
3706 framebuffer->getStencilOrDepthStencilAttachment();
3707 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003708 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003709 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003710
3711 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3712 bool differentWritemasks =
3713 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3714 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3715 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3716 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3717
3718 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003719 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003720 if (!context->getExtensions().webglCompatibility)
3721 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003722 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3723 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003724 }
Jamie Madill437fa652016-05-03 15:13:24 -04003725 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003726 return false;
3727 }
Jamie Madillac528012014-06-20 13:21:23 -04003728 }
3729
Jamie Madilldd43e6c2017-03-24 14:18:49 -04003730 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003731 {
Jamie Madill437fa652016-05-03 15:13:24 -04003732 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003733 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003734 }
3735
Geoff Lang7dd2e102014-11-10 15:19:26 -05003736 gl::Program *program = state.getProgram();
3737 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -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 Madilld4cfa572014-07-08 10:00:32 -04003741 }
3742
Geoff Lang7dd2e102014-11-10 15:19:26 -05003743 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003744 {
Jamie Madill437fa652016-05-03 15:13:24 -04003745 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003746 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003747 }
3748
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003749 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003750 for (unsigned int uniformBlockIndex = 0;
3751 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003752 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003753 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003754 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003755 const OffsetBindingPointer<Buffer> &uniformBuffer =
3756 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003757
Geoff Lang5d124a62015-09-15 13:03:27 -04003758 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003759 {
3760 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003761 context->handleError(
3762 Error(GL_INVALID_OPERATION,
3763 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003764 return false;
3765 }
3766
Geoff Lang5d124a62015-09-15 13:03:27 -04003767 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003768 if (uniformBufferSize == 0)
3769 {
3770 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003771 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003772 }
3773
Jamie Madill62d31cb2015-09-11 13:25:51 -04003774 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003775 {
3776 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003777 context->handleError(
3778 Error(GL_INVALID_OPERATION,
3779 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003780 return false;
3781 }
3782 }
3783
Jamie Madilla4595b82017-01-11 17:36:34 -05003784 // Detect rendering feedback loops for WebGL.
3785 if (context->getExtensions().webglCompatibility)
3786 {
3787 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3788 {
3789 context->handleError(
3790 Error(GL_INVALID_OPERATION,
3791 "Rendering feedback loop formed between Framebuffer and active Texture."));
3792 return false;
3793 }
3794 }
3795
Jamie Madill250d33f2014-06-06 17:09:03 -04003796 // No-op if zero count
3797 return (count > 0);
3798}
3799
Jamie Madillc1d770e2017-04-13 17:31:24 -04003800bool ValidateDrawArraysCommon(ValidationContext *context,
3801 GLenum mode,
3802 GLint first,
3803 GLsizei count,
3804 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003805{
Jamie Madillfd716582014-06-06 17:09:04 -04003806 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003807 {
Jamie Madill437fa652016-05-03 15:13:24 -04003808 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003809 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003810 }
3811
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003812 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003813 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003814 if (curTransformFeedback && curTransformFeedback->isActive() &&
3815 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003816 {
3817 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003818 // that does not match the current transform feedback object's draw mode (if transform
3819 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003820 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003821 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003822 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003823 }
3824
Jiajia Qind9671222016-11-29 16:30:31 +08003825 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003826 {
3827 return false;
3828 }
3829
Corentin Wallez71168a02016-12-19 15:11:18 -08003830 // Check the computation of maxVertex doesn't overflow.
3831 // - first < 0 or count < 0 have been checked as an error condition
3832 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3833 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3834 ASSERT(count > 0 && first >= 0);
3835 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3836 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003837 {
3838 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3839 return false;
3840 }
3841
Corentin Wallez71168a02016-12-19 15:11:18 -08003842 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003843 {
3844 return false;
3845 }
3846
3847 return true;
3848}
3849
He Yunchaoced53ae2016-11-29 15:00:51 +08003850bool ValidateDrawArraysInstanced(Context *context,
3851 GLenum mode,
3852 GLint first,
3853 GLsizei count,
3854 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003855{
Geoff Lang407d4e72017-04-12 14:54:11 -04003856 if (context->getExtensions().webglCompatibility && !ValidateDrawInstancedANGLEAndWebGL(context))
Jamie Madillfd716582014-06-06 17:09:04 -04003857 {
3858 return false;
3859 }
3860
Geoff Lang407d4e72017-04-12 14:54:11 -04003861 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04003862}
3863
He Yunchaoced53ae2016-11-29 15:00:51 +08003864bool ValidateDrawArraysInstancedANGLE(Context *context,
3865 GLenum mode,
3866 GLint first,
3867 GLsizei count,
3868 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003869{
Geoff Lang407d4e72017-04-12 14:54:11 -04003870 if (!ValidateDrawInstancedANGLEAndWebGL(context))
Geoff Lang87a93302014-09-16 13:29:43 -04003871 {
3872 return false;
3873 }
3874
Geoff Lang407d4e72017-04-12 14:54:11 -04003875 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04003876}
3877
Jiajia Qind9671222016-11-29 16:30:31 +08003878bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003879{
Jamie Madill250d33f2014-06-06 17:09:03 -04003880 switch (type)
3881 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003882 case GL_UNSIGNED_BYTE:
3883 case GL_UNSIGNED_SHORT:
3884 break;
3885 case GL_UNSIGNED_INT:
3886 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3887 {
3888 context->handleError(Error(GL_INVALID_ENUM));
3889 return false;
3890 }
3891 break;
3892 default:
3893 context->handleError(Error(GL_INVALID_ENUM));
3894 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003895 }
3896
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003897 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003898
3899 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003900 if (curTransformFeedback && curTransformFeedback->isActive() &&
3901 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003902 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003903 // It is an invalid operation to call DrawElements, DrawRangeElements or
3904 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003905 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003906 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003907 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003908 }
3909
Jiajia Qind9671222016-11-29 16:30:31 +08003910 return true;
3911}
3912
3913bool ValidateDrawElements(ValidationContext *context,
3914 GLenum mode,
3915 GLsizei count,
3916 GLenum type,
3917 const GLvoid *indices,
3918 GLsizei primcount,
3919 IndexRange *indexRangeOut)
3920{
3921 if (!ValidateDrawElementsBase(context, type))
3922 return false;
3923
3924 const State &state = context->getGLState();
3925
Jamie Madill250d33f2014-06-06 17:09:03 -04003926 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003927 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003928 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003929 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04003930 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003931 }
3932
He Yunchaoced53ae2016-11-29 15:00:51 +08003933 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003934 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003935
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003936 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3937
3938 if (context->getExtensions().webglCompatibility)
3939 {
3940 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3941 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3942 {
3943 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3944 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3945 // data type passed to the call, or an INVALID_OPERATION error is generated.
3946 context->handleError(Error(GL_INVALID_OPERATION,
3947 "indices must be a multiple of the element type size."));
3948 return false;
3949 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003950
3951 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3952 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3953 // error is generated.
3954 if (reinterpret_cast<intptr_t>(indices) < 0)
3955 {
3956 context->handleError(Error(GL_INVALID_VALUE, "Offset < 0."));
3957 return false;
3958 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003959 }
3960
3961 if (context->getExtensions().webglCompatibility ||
3962 !context->getGLState().areClientArraysEnabled())
3963 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003964 if (!elementArrayBuffer && count > 0)
3965 {
3966 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3967 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3968 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3969 context->handleError(Error(GL_INVALID_OPERATION,
3970 "There is no element array buffer bound and count > 0."));
3971 return false;
3972 }
3973 }
3974
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003975 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003976 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003977 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003978 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003979 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3980 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3981 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3982 constexpr uint64_t kMaxTypeSize = 8;
3983 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3984 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3985 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003986
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003987 uint64_t typeSize = typeBytes;
3988 uint64_t elementCount = static_cast<uint64_t>(count);
3989 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3990
3991 // Doing the multiplication here is overflow-safe
3992 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3993
3994 // The offset can be any value, check for overflows
3995 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3996 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003997 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003998 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003999 return false;
4000 }
4001
Corentin Wallezfe9306a2017-02-01 17:41:05 -05004002 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
4003 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05004004 {
4005 context->handleError(
4006 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
4007 return false;
4008 }
4009 }
4010 else if (!indices)
4011 {
4012 // This is an application error that would normally result in a crash,
4013 // but we catch it and return an error
4014 context->handleError(
4015 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04004016 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04004017 }
Jamie Madillae3000b2014-08-25 15:47:51 -04004018 }
4019
Jiajia Qind9671222016-11-29 16:30:31 +08004020 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07004021 {
4022 return false;
4023 }
4024
Jamie Madill2b976812014-08-25 15:47:49 -04004025 // Use max index to validate if our vertex buffers are large enough for the pull.
4026 // TODO: offer fast path, with disabled index validation.
4027 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
4028 if (elementArrayBuffer)
4029 {
Jacek Cabana5521de2014-10-01 17:23:46 +02004030 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04004031 Error error =
4032 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
4033 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04004034 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04004035 {
Jamie Madill437fa652016-05-03 15:13:24 -04004036 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04004037 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04004038 }
4039 }
4040 else
4041 {
Geoff Lang3edfe032015-09-04 16:38:24 -04004042 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04004043 }
4044
Jamie Madille79b1e12015-11-04 16:36:37 -05004045 // If we use an index greater than our maximum supported index range, return an error.
4046 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
4047 // return an error if possible here.
4048 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
4049 {
Jamie Madill437fa652016-05-03 15:13:24 -04004050 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05004051 return false;
4052 }
4053
Corentin Wallez92db6942016-12-09 13:10:36 -05004054 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
4055 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04004056 {
4057 return false;
4058 }
4059
Geoff Lang3edfe032015-09-04 16:38:24 -04004060 // No op if there are no real indices in the index data (all are primitive restart).
4061 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04004062}
4063
Geoff Langb1196682014-07-23 13:47:29 -04004064bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04004065 GLenum mode,
4066 GLsizei count,
4067 GLenum type,
4068 const GLvoid *indices,
4069 GLsizei primcount,
4070 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04004071{
Geoff Lang407d4e72017-04-12 14:54:11 -04004072 if (context->getExtensions().webglCompatibility && !ValidateDrawInstancedANGLEAndWebGL(context))
Jamie Madillfd716582014-06-06 17:09:04 -04004073 {
4074 return false;
4075 }
4076
Geoff Lang407d4e72017-04-12 14:54:11 -04004077 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount,
4078 indexRangeOut);
Jamie Madill250d33f2014-06-06 17:09:03 -04004079}
4080
Geoff Lang3edfe032015-09-04 16:38:24 -04004081bool ValidateDrawElementsInstancedANGLE(Context *context,
4082 GLenum mode,
4083 GLsizei count,
4084 GLenum type,
4085 const GLvoid *indices,
4086 GLsizei primcount,
4087 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04004088{
Geoff Lang407d4e72017-04-12 14:54:11 -04004089 if (!ValidateDrawInstancedANGLEAndWebGL(context))
Geoff Lang87a93302014-09-16 13:29:43 -04004090 {
4091 return false;
4092 }
4093
Geoff Lang407d4e72017-04-12 14:54:11 -04004094 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount,
4095 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04004096}
4097
He Yunchaoced53ae2016-11-29 15:00:51 +08004098bool ValidateFramebufferTextureBase(Context *context,
4099 GLenum target,
4100 GLenum attachment,
4101 GLuint texture,
4102 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04004103{
Jamie Madill55ec3b12014-07-03 10:38:57 -04004104 if (!ValidFramebufferTarget(target))
4105 {
Jamie Madill437fa652016-05-03 15:13:24 -04004106 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04004107 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004108 }
4109
4110 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04004111 {
4112 return false;
4113 }
4114
Jamie Madill55ec3b12014-07-03 10:38:57 -04004115 if (texture != 0)
4116 {
4117 gl::Texture *tex = context->getTexture(texture);
4118
Yunchao He4f285442017-04-21 12:15:49 +08004119 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04004120 {
Jamie Madill437fa652016-05-03 15:13:24 -04004121 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04004122 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004123 }
4124
4125 if (level < 0)
4126 {
Jamie Madill437fa652016-05-03 15:13:24 -04004127 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04004128 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004129 }
4130 }
4131
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004132 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04004133 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04004134
Jamie Madill84115c92015-04-23 15:00:07 -04004135 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04004136 {
Jamie Madill437fa652016-05-03 15:13:24 -04004137 context->handleError(
4138 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04004139 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004140 }
4141
4142 return true;
4143}
4144
He Yunchaoced53ae2016-11-29 15:00:51 +08004145bool ValidateFramebufferTexture2D(Context *context,
4146 GLenum target,
4147 GLenum attachment,
4148 GLenum textarget,
4149 GLuint texture,
4150 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04004151{
He Yunchaoced53ae2016-11-29 15:00:51 +08004152 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
4153 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03004154 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
4155 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04004156 {
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 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04004162 {
4163 return false;
4164 }
4165
Jamie Madill55ec3b12014-07-03 10:38:57 -04004166 if (texture != 0)
4167 {
4168 gl::Texture *tex = context->getTexture(texture);
4169 ASSERT(tex);
4170
Jamie Madill2a6564e2014-07-11 09:53:19 -04004171 const gl::Caps &caps = context->getCaps();
4172
Jamie Madill55ec3b12014-07-03 10:38:57 -04004173 switch (textarget)
4174 {
He Yunchaoced53ae2016-11-29 15:00:51 +08004175 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04004176 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04004177 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04004178 {
Jamie Madill437fa652016-05-03 15:13:24 -04004179 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04004180 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004181 }
4182 if (tex->getTarget() != GL_TEXTURE_2D)
4183 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08004184 context->handleError(Error(GL_INVALID_OPERATION,
4185 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04004186 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004187 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04004188 }
4189 break;
4190
He Yunchaoced53ae2016-11-29 15:00:51 +08004191 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4192 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4193 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4194 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4195 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4196 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04004197 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04004198 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04004199 {
Jamie Madill437fa652016-05-03 15:13:24 -04004200 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04004201 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004202 }
4203 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
4204 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08004205 context->handleError(Error(GL_INVALID_OPERATION,
4206 "Textarget must match the texture target type."));
4207 return false;
4208 }
4209 }
4210 break;
4211
4212 case GL_TEXTURE_2D_MULTISAMPLE:
4213 {
4214 if (context->getClientVersion() < ES_3_1)
4215 {
4216 context->handleError(Error(GL_INVALID_OPERATION,
4217 "Texture target requires at least OpenGL ES 3.1."));
4218 return false;
4219 }
4220
4221 if (level != 0)
4222 {
4223 context->handleError(
4224 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
4225 return false;
4226 }
4227 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
4228 {
4229 context->handleError(Error(GL_INVALID_OPERATION,
4230 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04004231 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004232 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04004233 }
4234 break;
4235
He Yunchaoced53ae2016-11-29 15:00:51 +08004236 default:
4237 context->handleError(Error(GL_INVALID_ENUM));
4238 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004239 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05004240
Jamie Madilla3944d42016-07-22 22:13:26 -04004241 const Format &format = tex->getFormat(textarget, level);
4242 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05004243 {
Jamie Madill437fa652016-05-03 15:13:24 -04004244 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05004245 return false;
4246 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04004247 }
4248
Jamie Madill570f7c82014-07-03 10:38:54 -04004249 return true;
4250}
4251
Geoff Langb1196682014-07-23 13:47:29 -04004252bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04004253{
4254 if (program == 0)
4255 {
Jamie Madill437fa652016-05-03 15:13:24 -04004256 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04004257 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04004258 }
4259
Dian Xiang769769a2015-09-09 15:20:08 -07004260 gl::Program *programObject = GetValidProgram(context, program);
4261 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05004262 {
4263 return false;
4264 }
4265
Jamie Madill0063c512014-08-25 15:47:53 -04004266 if (!programObject || !programObject->isLinked())
4267 {
Jamie Madill437fa652016-05-03 15:13:24 -04004268 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04004269 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04004270 }
4271
Geoff Lang7dd2e102014-11-10 15:19:26 -05004272 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04004273 {
Jamie Madill437fa652016-05-03 15:13:24 -04004274 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04004275 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04004276 }
4277
Jamie Madill0063c512014-08-25 15:47:53 -04004278 return true;
4279}
4280
He Yunchaoced53ae2016-11-29 15:00:51 +08004281bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04004282{
4283 return ValidateGetUniformBase(context, program, location);
4284}
4285
He Yunchaoced53ae2016-11-29 15:00:51 +08004286bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04004287{
Jamie Madill78f41802014-08-25 15:47:55 -04004288 return ValidateGetUniformBase(context, program, location);
4289}
4290
Geoff Langf41d0ee2016-10-07 13:04:23 -04004291static bool ValidateSizedGetUniform(Context *context,
4292 GLuint program,
4293 GLint location,
4294 GLsizei bufSize,
4295 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04004296{
Geoff Langf41d0ee2016-10-07 13:04:23 -04004297 if (length)
4298 {
4299 *length = 0;
4300 }
4301
Jamie Madill78f41802014-08-25 15:47:55 -04004302 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04004303 {
Jamie Madill78f41802014-08-25 15:47:55 -04004304 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04004305 }
4306
Geoff Langf41d0ee2016-10-07 13:04:23 -04004307 if (bufSize < 0)
4308 {
4309 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4310 return false;
4311 }
4312
Jamie Madilla502c742014-08-28 17:19:13 -04004313 gl::Program *programObject = context->getProgram(program);
4314 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04004315
Jamie Madill78f41802014-08-25 15:47:55 -04004316 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04004317 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08004318 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04004319 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04004320 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04004321 context->handleError(
4322 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04004323 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04004324 }
4325
Geoff Langf41d0ee2016-10-07 13:04:23 -04004326 if (length)
4327 {
Geoff Lang94177fb2016-11-14 16:12:26 -05004328 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04004329 }
4330
Jamie Madill0063c512014-08-25 15:47:53 -04004331 return true;
4332}
4333
He Yunchaoced53ae2016-11-29 15:00:51 +08004334bool ValidateGetnUniformfvEXT(Context *context,
4335 GLuint program,
4336 GLint location,
4337 GLsizei bufSize,
4338 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04004339{
Geoff Langf41d0ee2016-10-07 13:04:23 -04004340 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04004341}
4342
He Yunchaoced53ae2016-11-29 15:00:51 +08004343bool ValidateGetnUniformivEXT(Context *context,
4344 GLuint program,
4345 GLint location,
4346 GLsizei bufSize,
4347 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04004348{
Geoff Langf41d0ee2016-10-07 13:04:23 -04004349 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
4350}
4351
4352bool ValidateGetUniformfvRobustANGLE(Context *context,
4353 GLuint program,
4354 GLint location,
4355 GLsizei bufSize,
4356 GLsizei *length,
4357 GLfloat *params)
4358{
4359 if (!ValidateRobustEntryPoint(context, bufSize))
4360 {
4361 return false;
4362 }
4363
4364 // bufSize is validated in ValidateSizedGetUniform
4365 return ValidateSizedGetUniform(context, program, location, bufSize, length);
4366}
4367
4368bool ValidateGetUniformivRobustANGLE(Context *context,
4369 GLuint program,
4370 GLint location,
4371 GLsizei bufSize,
4372 GLsizei *length,
4373 GLint *params)
4374{
4375 if (!ValidateRobustEntryPoint(context, bufSize))
4376 {
4377 return false;
4378 }
4379
4380 // bufSize is validated in ValidateSizedGetUniform
4381 return ValidateSizedGetUniform(context, program, location, bufSize, length);
4382}
4383
4384bool ValidateGetUniformuivRobustANGLE(Context *context,
4385 GLuint program,
4386 GLint location,
4387 GLsizei bufSize,
4388 GLsizei *length,
4389 GLuint *params)
4390{
4391 if (!ValidateRobustEntryPoint(context, bufSize))
4392 {
4393 return false;
4394 }
4395
4396 if (context->getClientMajorVersion() < 3)
4397 {
4398 context->handleError(
4399 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
4400 return false;
4401 }
4402
4403 // bufSize is validated in ValidateSizedGetUniform
4404 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04004405}
4406
He Yunchaoced53ae2016-11-29 15:00:51 +08004407bool ValidateDiscardFramebufferBase(Context *context,
4408 GLenum target,
4409 GLsizei numAttachments,
4410 const GLenum *attachments,
4411 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07004412{
4413 if (numAttachments < 0)
4414 {
Jamie Madill437fa652016-05-03 15:13:24 -04004415 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07004416 return false;
4417 }
4418
4419 for (GLsizei i = 0; i < numAttachments; ++i)
4420 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02004421 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07004422 {
4423 if (defaultFramebuffer)
4424 {
Jamie Madill437fa652016-05-03 15:13:24 -04004425 context->handleError(Error(
4426 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07004427 return false;
4428 }
4429
4430 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
4431 {
Jamie Madill437fa652016-05-03 15:13:24 -04004432 context->handleError(Error(GL_INVALID_OPERATION,
4433 "Requested color attachment is greater than the maximum "
4434 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07004435 return false;
4436 }
4437 }
4438 else
4439 {
4440 switch (attachments[i])
4441 {
He Yunchaoced53ae2016-11-29 15:00:51 +08004442 case GL_DEPTH_ATTACHMENT:
4443 case GL_STENCIL_ATTACHMENT:
4444 case GL_DEPTH_STENCIL_ATTACHMENT:
4445 if (defaultFramebuffer)
4446 {
4447 context->handleError(
4448 Error(GL_INVALID_ENUM,
4449 "Invalid attachment when the default framebuffer is bound"));
4450 return false;
4451 }
4452 break;
4453 case GL_COLOR:
4454 case GL_DEPTH:
4455 case GL_STENCIL:
4456 if (!defaultFramebuffer)
4457 {
4458 context->handleError(
4459 Error(GL_INVALID_ENUM,
4460 "Invalid attachment when the default framebuffer is not bound"));
4461 return false;
4462 }
4463 break;
4464 default:
4465 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07004466 return false;
Austin Kinross08332632015-05-05 13:35:47 -07004467 }
4468 }
4469 }
4470
4471 return true;
4472}
4473
Austin Kinross6ee1e782015-05-29 17:05:37 -07004474bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
4475{
4476 // Note that debug marker calls must not set error state
4477
4478 if (length < 0)
4479 {
4480 return false;
4481 }
4482
4483 if (marker == nullptr)
4484 {
4485 return false;
4486 }
4487
4488 return true;
4489}
4490
4491bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
4492{
4493 // Note that debug marker calls must not set error state
4494
4495 if (length < 0)
4496 {
4497 return false;
4498 }
4499
4500 if (length > 0 && marker == nullptr)
4501 {
4502 return false;
4503 }
4504
4505 return true;
4506}
4507
Geoff Langdcab33b2015-07-21 13:03:16 -04004508bool ValidateEGLImageTargetTexture2DOES(Context *context,
4509 egl::Display *display,
4510 GLenum target,
4511 egl::Image *image)
4512{
Geoff Langa8406172015-07-21 16:53:39 -04004513 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4514 {
Jamie Madill437fa652016-05-03 15:13:24 -04004515 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004516 return false;
4517 }
4518
4519 switch (target)
4520 {
4521 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004522 if (!context->getExtensions().eglImage)
4523 {
4524 context->handleError(Error(
4525 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4526 }
4527 break;
4528
4529 case GL_TEXTURE_EXTERNAL_OES:
4530 if (!context->getExtensions().eglImageExternal)
4531 {
4532 context->handleError(Error(
4533 GL_INVALID_ENUM,
4534 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4535 }
Geoff Langa8406172015-07-21 16:53:39 -04004536 break;
4537
4538 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004539 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004540 return false;
4541 }
4542
4543 if (!display->isValidImage(image))
4544 {
Jamie Madill437fa652016-05-03 15:13:24 -04004545 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004546 return false;
4547 }
4548
4549 if (image->getSamples() > 0)
4550 {
Jamie Madill437fa652016-05-03 15:13:24 -04004551 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004552 "cannot create a 2D texture from a multisampled EGL image."));
4553 return false;
4554 }
4555
Geoff Langca271392017-04-05 12:30:00 -04004556 const TextureCaps &textureCaps =
4557 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04004558 if (!textureCaps.texturable)
4559 {
Jamie Madill437fa652016-05-03 15:13:24 -04004560 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004561 "EGL image internal format is not supported as a texture."));
4562 return false;
4563 }
4564
Geoff Langdcab33b2015-07-21 13:03:16 -04004565 return true;
4566}
4567
4568bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4569 egl::Display *display,
4570 GLenum target,
4571 egl::Image *image)
4572{
Geoff Langa8406172015-07-21 16:53:39 -04004573 if (!context->getExtensions().eglImage)
4574 {
Jamie Madill437fa652016-05-03 15:13:24 -04004575 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004576 return false;
4577 }
4578
4579 switch (target)
4580 {
4581 case GL_RENDERBUFFER:
4582 break;
4583
4584 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004585 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004586 return false;
4587 }
4588
4589 if (!display->isValidImage(image))
4590 {
Jamie Madill437fa652016-05-03 15:13:24 -04004591 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004592 return false;
4593 }
4594
Geoff Langca271392017-04-05 12:30:00 -04004595 const TextureCaps &textureCaps =
4596 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04004597 if (!textureCaps.renderable)
4598 {
Jamie Madill437fa652016-05-03 15:13:24 -04004599 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004600 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4601 return false;
4602 }
4603
Geoff Langdcab33b2015-07-21 13:03:16 -04004604 return true;
4605}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004606
4607bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4608{
Geoff Lang36167ab2015-12-07 10:27:14 -05004609 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004610 {
4611 // The default VAO should always exist
4612 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004613 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004614 return false;
4615 }
4616
4617 return true;
4618}
4619
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004620bool ValidateLinkProgram(Context *context, GLuint program)
4621{
4622 if (context->hasActiveTransformFeedback(program))
4623 {
4624 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004625 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004626 "Cannot link program while program is associated with an active "
4627 "transform feedback object."));
4628 return false;
4629 }
Jamie Madillc1d770e2017-04-13 17:31:24 -04004630
4631 Program *programObject = GetValidProgram(context, program);
4632 if (!programObject)
4633 {
4634 return false;
4635 }
4636
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004637 return true;
4638}
4639
Geoff Langc5629752015-12-07 16:29:04 -05004640bool ValidateProgramBinaryBase(Context *context,
4641 GLuint program,
4642 GLenum binaryFormat,
4643 const void *binary,
4644 GLint length)
4645{
4646 Program *programObject = GetValidProgram(context, program);
4647 if (programObject == nullptr)
4648 {
4649 return false;
4650 }
4651
4652 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4653 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4654 programBinaryFormats.end())
4655 {
Jamie Madill437fa652016-05-03 15:13:24 -04004656 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004657 return false;
4658 }
4659
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004660 if (context->hasActiveTransformFeedback(program))
4661 {
4662 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004663 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004664 "Cannot change program binary while program is associated with "
4665 "an active transform feedback object."));
4666 return false;
4667 }
4668
Geoff Langc5629752015-12-07 16:29:04 -05004669 return true;
4670}
4671
4672bool ValidateGetProgramBinaryBase(Context *context,
4673 GLuint program,
4674 GLsizei bufSize,
4675 GLsizei *length,
4676 GLenum *binaryFormat,
4677 void *binary)
4678{
4679 Program *programObject = GetValidProgram(context, program);
4680 if (programObject == nullptr)
4681 {
4682 return false;
4683 }
4684
4685 if (!programObject->isLinked())
4686 {
Jamie Madill437fa652016-05-03 15:13:24 -04004687 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004688 return false;
4689 }
4690
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004691 if (context->getCaps().programBinaryFormats.empty())
4692 {
4693 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4694 return false;
4695 }
4696
Geoff Langc5629752015-12-07 16:29:04 -05004697 return true;
4698}
Jamie Madillc29968b2016-01-20 11:17:23 -05004699
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004700bool ValidateUseProgram(Context *context, GLuint program)
4701{
4702 if (program != 0)
4703 {
4704 Program *programObject = context->getProgram(program);
4705 if (!programObject)
4706 {
4707 // ES 3.1.0 section 7.3 page 72
4708 if (context->getShader(program))
4709 {
Jamie Madill437fa652016-05-03 15:13:24 -04004710 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004711 Error(GL_INVALID_OPERATION,
4712 "Attempted to use a single shader instead of a shader program."));
4713 return false;
4714 }
4715 else
4716 {
Jamie Madill437fa652016-05-03 15:13:24 -04004717 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004718 return false;
4719 }
4720 }
4721 if (!programObject->isLinked())
4722 {
Jamie Madill437fa652016-05-03 15:13:24 -04004723 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004724 return false;
4725 }
4726 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004727 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004728 {
4729 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004730 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004731 Error(GL_INVALID_OPERATION,
4732 "Cannot change active program while transform feedback is unpaused."));
4733 return false;
4734 }
4735
4736 return true;
4737}
4738
Jamie Madillc29968b2016-01-20 11:17:23 -05004739bool ValidateCopyTexImage2D(ValidationContext *context,
4740 GLenum target,
4741 GLint level,
4742 GLenum internalformat,
4743 GLint x,
4744 GLint y,
4745 GLsizei width,
4746 GLsizei height,
4747 GLint border)
4748{
Martin Radev1be913c2016-07-11 17:59:16 +03004749 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004750 {
4751 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4752 0, x, y, width, height, border);
4753 }
4754
Martin Radev1be913c2016-07-11 17:59:16 +03004755 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004756 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4757 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004758}
Jamie Madillc29968b2016-01-20 11:17:23 -05004759
4760bool ValidateFramebufferRenderbuffer(Context *context,
4761 GLenum target,
4762 GLenum attachment,
4763 GLenum renderbuffertarget,
4764 GLuint renderbuffer)
4765{
4766 if (!ValidFramebufferTarget(target) ||
4767 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4768 {
Jamie Madill437fa652016-05-03 15:13:24 -04004769 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004770 return false;
4771 }
4772
4773 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4774 renderbuffertarget, renderbuffer);
4775}
4776
4777bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4778{
4779 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4780 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4781 {
Jamie Madill437fa652016-05-03 15:13:24 -04004782 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004783 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4784 return false;
4785 }
4786
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004787 ASSERT(context->getGLState().getDrawFramebuffer());
4788 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004789 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4790
4791 // This should come first before the check for the default frame buffer
4792 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4793 // rather than INVALID_OPERATION
4794 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4795 {
4796 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4797
4798 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004799 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4800 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004801 {
4802 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004803 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4804 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4805 // 3.1 is still a bit ambiguous about the error, but future specs are
4806 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004807 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004808 return false;
4809 }
4810 else if (bufs[colorAttachment] >= maxColorAttachment)
4811 {
Jamie Madill437fa652016-05-03 15:13:24 -04004812 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004813 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004814 return false;
4815 }
4816 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4817 frameBufferId != 0)
4818 {
4819 // INVALID_OPERATION-GL is bound to buffer and ith argument
4820 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004821 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004822 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4823 return false;
4824 }
4825 }
4826
4827 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4828 // and n is not 1 or bufs is bound to value other than BACK and NONE
4829 if (frameBufferId == 0)
4830 {
4831 if (n != 1)
4832 {
Jamie Madill437fa652016-05-03 15:13:24 -04004833 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004834 "n must be 1 when GL is bound to the default framebuffer"));
4835 return false;
4836 }
4837
4838 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4839 {
Jamie Madill437fa652016-05-03 15:13:24 -04004840 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004841 GL_INVALID_OPERATION,
4842 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4843 return false;
4844 }
4845 }
4846
4847 return true;
4848}
4849
4850bool ValidateCopyTexSubImage2D(Context *context,
4851 GLenum target,
4852 GLint level,
4853 GLint xoffset,
4854 GLint yoffset,
4855 GLint x,
4856 GLint y,
4857 GLsizei width,
4858 GLsizei height)
4859{
Martin Radev1be913c2016-07-11 17:59:16 +03004860 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004861 {
4862 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4863 yoffset, x, y, width, height, 0);
4864 }
4865
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004866 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4867 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004868}
4869
Geoff Lang496c02d2016-10-20 11:38:11 -07004870bool ValidateGetBufferPointervBase(Context *context,
4871 GLenum target,
4872 GLenum pname,
4873 GLsizei *length,
4874 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004875{
Geoff Lang496c02d2016-10-20 11:38:11 -07004876 if (length)
4877 {
4878 *length = 0;
4879 }
4880
4881 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4882 {
4883 context->handleError(
4884 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004885 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004886 return false;
4887 }
4888
Olli Etuaho4f667482016-03-30 15:56:35 +03004889 if (!ValidBufferTarget(context, target))
4890 {
Jamie Madill437fa652016-05-03 15:13:24 -04004891 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004892 return false;
4893 }
4894
Geoff Lang496c02d2016-10-20 11:38:11 -07004895 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004896 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004897 case GL_BUFFER_MAP_POINTER:
4898 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004899
Geoff Lang496c02d2016-10-20 11:38:11 -07004900 default:
4901 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4902 return false;
4903 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004904
4905 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4906 // target bound to zero generate an INVALID_OPERATION error."
4907 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004908 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004909 {
Jamie Madill437fa652016-05-03 15:13:24 -04004910 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004911 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4912 return false;
4913 }
4914
Geoff Lang496c02d2016-10-20 11:38:11 -07004915 if (length)
4916 {
4917 *length = 1;
4918 }
4919
Olli Etuaho4f667482016-03-30 15:56:35 +03004920 return true;
4921}
4922
4923bool ValidateUnmapBufferBase(Context *context, GLenum target)
4924{
4925 if (!ValidBufferTarget(context, target))
4926 {
Jamie Madill437fa652016-05-03 15:13:24 -04004927 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004928 return false;
4929 }
4930
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004931 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004932
4933 if (buffer == nullptr || !buffer->isMapped())
4934 {
Jamie Madill437fa652016-05-03 15:13:24 -04004935 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004936 return false;
4937 }
4938
4939 return true;
4940}
4941
4942bool ValidateMapBufferRangeBase(Context *context,
4943 GLenum target,
4944 GLintptr offset,
4945 GLsizeiptr length,
4946 GLbitfield access)
4947{
4948 if (!ValidBufferTarget(context, target))
4949 {
Jamie Madill437fa652016-05-03 15:13:24 -04004950 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004951 return false;
4952 }
4953
4954 if (offset < 0 || length < 0)
4955 {
Jamie Madill437fa652016-05-03 15:13:24 -04004956 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004957 return false;
4958 }
4959
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004960 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004961
4962 if (!buffer)
4963 {
Jamie Madill437fa652016-05-03 15:13:24 -04004964 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004965 return false;
4966 }
4967
4968 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004969 CheckedNumeric<size_t> checkedOffset(offset);
4970 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004971
Jamie Madille2e406c2016-06-02 13:04:10 -04004972 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004973 {
Jamie Madill437fa652016-05-03 15:13:24 -04004974 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004975 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4976 return false;
4977 }
4978
4979 // Check for invalid bits in the mask
4980 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4981 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4982 GL_MAP_UNSYNCHRONIZED_BIT;
4983
4984 if (access & ~(allAccessBits))
4985 {
Jamie Madill437fa652016-05-03 15:13:24 -04004986 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004987 return false;
4988 }
4989
4990 if (length == 0)
4991 {
Jamie Madill437fa652016-05-03 15:13:24 -04004992 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004993 return false;
4994 }
4995
4996 if (buffer->isMapped())
4997 {
Jamie Madill437fa652016-05-03 15:13:24 -04004998 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004999 return false;
5000 }
5001
5002 // Check for invalid bit combinations
5003 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
5004 {
Jamie Madill437fa652016-05-03 15:13:24 -04005005 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03005006 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
5007 return false;
5008 }
5009
5010 GLbitfield writeOnlyBits =
5011 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
5012
5013 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
5014 {
Jamie Madill437fa652016-05-03 15:13:24 -04005015 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03005016 "Invalid access bits when mapping buffer for reading: 0x%X.",
5017 access));
5018 return false;
5019 }
5020
5021 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
5022 {
Jamie Madill437fa652016-05-03 15:13:24 -04005023 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03005024 GL_INVALID_OPERATION,
5025 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
5026 return false;
5027 }
5028 return true;
5029}
5030
5031bool ValidateFlushMappedBufferRangeBase(Context *context,
5032 GLenum target,
5033 GLintptr offset,
5034 GLsizeiptr length)
5035{
5036 if (offset < 0 || length < 0)
5037 {
Jamie Madill437fa652016-05-03 15:13:24 -04005038 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03005039 return false;
5040 }
5041
5042 if (!ValidBufferTarget(context, target))
5043 {
Jamie Madill437fa652016-05-03 15:13:24 -04005044 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03005045 return false;
5046 }
5047
Jamie Madilldfde6ab2016-06-09 07:07:18 -07005048 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03005049
5050 if (buffer == nullptr)
5051 {
Jamie Madill437fa652016-05-03 15:13:24 -04005052 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03005053 return false;
5054 }
5055
5056 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
5057 {
Jamie Madill437fa652016-05-03 15:13:24 -04005058 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03005059 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
5060 return false;
5061 }
5062
5063 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04005064 CheckedNumeric<size_t> checkedOffset(offset);
5065 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03005066
Jamie Madille2e406c2016-06-02 13:04:10 -04005067 if (!checkedSize.IsValid() ||
5068 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03005069 {
Jamie Madill437fa652016-05-03 15:13:24 -04005070 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03005071 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
5072 return false;
5073 }
5074
5075 return true;
5076}
5077
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005078bool ValidateGenerateMipmap(Context *context, GLenum target)
5079{
5080 if (!ValidTextureTarget(context, target))
5081 {
5082 context->handleError(Error(GL_INVALID_ENUM));
5083 return false;
5084 }
5085
5086 Texture *texture = context->getTargetTexture(target);
5087
5088 if (texture == nullptr)
5089 {
5090 context->handleError(Error(GL_INVALID_OPERATION));
5091 return false;
5092 }
5093
5094 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5095
5096 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5097 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5098 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5099 {
5100 context->handleError(Error(GL_INVALID_OPERATION));
5101 return false;
5102 }
5103
Jamie Madilla3944d42016-07-22 22:13:26 -04005104 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
5105 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
Geoff Langca271392017-04-05 12:30:00 -04005106 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005107
5108 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
5109 // unsized formats or that are color renderable and filterable. Since we do not track if
5110 // the texture was created with sized or unsized format (only sized formats are stored),
5111 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
5112 // be able to) because they aren't color renderable. Simply do a special case for LUMA
5113 // textures since they're the only texture format that can be created with unsized formats
5114 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
5115 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04005116 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
5117 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005118 {
5119 context->handleError(Error(GL_INVALID_OPERATION));
5120 return false;
5121 }
5122
5123 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04005124 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005125 {
5126 context->handleError(Error(GL_INVALID_OPERATION));
5127 return false;
5128 }
5129
5130 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05005131 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005132 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5133 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5134 {
Geoff Lang55482a12016-11-21 16:54:01 -05005135 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005136 context->handleError(Error(GL_INVALID_OPERATION));
5137 return false;
5138 }
5139
5140 // Cube completeness check
5141 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
5142 {
5143 context->handleError(Error(GL_INVALID_OPERATION));
5144 return false;
5145 }
5146
5147 return true;
5148}
5149
Olli Etuaho41997e72016-03-10 13:38:39 +02005150bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5151{
5152 return ValidateGenOrDelete(context, n);
5153}
5154
5155bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5156{
5157 return ValidateGenOrDelete(context, n);
5158}
5159
5160bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5161{
5162 return ValidateGenOrDelete(context, n);
5163}
5164
5165bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5166{
5167 return ValidateGenOrDelete(context, n);
5168}
5169
5170bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5171{
5172 return ValidateGenOrDelete(context, n);
5173}
5174
5175bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5176{
5177 return ValidateGenOrDelete(context, n);
5178}
5179
5180bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5181{
5182 return ValidateGenOrDelete(context, n);
5183}
5184
5185bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5186{
5187 return ValidateGenOrDelete(context, n);
5188}
5189
5190bool ValidateGenOrDelete(Context *context, GLint n)
5191{
5192 if (n < 0)
5193 {
Jamie Madill437fa652016-05-03 15:13:24 -04005194 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02005195 return false;
5196 }
5197 return true;
5198}
5199
Geoff Langf41a7152016-09-19 15:11:17 -04005200bool ValidateEnable(Context *context, GLenum cap)
5201{
5202 if (!ValidCap(context, cap, false))
5203 {
5204 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5205 return false;
5206 }
5207
5208 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5209 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5210 {
5211 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
5212 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
5213
5214 // We also output an error message to the debugger window if tracing is active, so that
5215 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05005216 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04005217 return false;
5218 }
5219
5220 return true;
5221}
5222
5223bool ValidateDisable(Context *context, GLenum cap)
5224{
5225 if (!ValidCap(context, cap, false))
5226 {
5227 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5228 return false;
5229 }
5230
5231 return true;
5232}
5233
5234bool ValidateIsEnabled(Context *context, GLenum cap)
5235{
5236 if (!ValidCap(context, cap, true))
5237 {
5238 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5239 return false;
5240 }
5241
5242 return true;
5243}
5244
Geoff Langff5b2d52016-09-07 11:32:23 -04005245bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
5246{
5247 if (!context->getExtensions().robustClientMemory)
5248 {
5249 context->handleError(
5250 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
5251 return false;
5252 }
5253
5254 if (bufSize < 0)
5255 {
5256 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
5257 return false;
5258 }
5259
5260 return true;
5261}
5262
Geoff Lang2e43dbb2016-10-14 12:27:35 -04005263bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
5264{
5265 if (bufSize < numParams)
5266 {
5267 context->handleError(Error(GL_INVALID_OPERATION,
5268 "%u parameters are required but %i were provided.", numParams,
5269 bufSize));
5270 return false;
5271 }
5272
5273 return true;
5274}
5275
Geoff Langff5b2d52016-09-07 11:32:23 -04005276bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5277 GLenum target,
5278 GLenum attachment,
5279 GLenum pname,
5280 GLsizei *numParams)
5281{
5282 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
Yunchao He33151a52017-04-13 09:58:17 +08005283 if (numParams)
5284 {
5285 *numParams = 1;
5286 }
Geoff Langff5b2d52016-09-07 11:32:23 -04005287
5288 if (!ValidFramebufferTarget(target))
5289 {
5290 context->handleError(Error(GL_INVALID_ENUM));
5291 return false;
5292 }
5293
5294 int clientVersion = context->getClientMajorVersion();
5295
5296 switch (pname)
5297 {
5298 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5299 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5300 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
5301 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
5302 break;
5303
5304 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
5305 if (clientVersion < 3 && !context->getExtensions().sRGB)
5306 {
5307 context->handleError(Error(GL_INVALID_ENUM));
5308 return false;
5309 }
5310 break;
5311
5312 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
5313 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
5314 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
5315 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
5316 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
5317 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
5318 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
5319 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
5320 if (clientVersion < 3)
5321 {
5322 context->handleError(Error(GL_INVALID_ENUM));
5323 return false;
5324 }
5325 break;
5326
5327 default:
5328 context->handleError(Error(GL_INVALID_ENUM));
5329 return false;
5330 }
5331
5332 // Determine if the attachment is a valid enum
5333 switch (attachment)
5334 {
5335 case GL_BACK:
5336 case GL_FRONT:
5337 case GL_DEPTH:
5338 case GL_STENCIL:
5339 case GL_DEPTH_STENCIL_ATTACHMENT:
5340 if (clientVersion < 3)
5341 {
5342 context->handleError(Error(GL_INVALID_ENUM));
5343 return false;
5344 }
5345 break;
5346
5347 case GL_DEPTH_ATTACHMENT:
5348 case GL_STENCIL_ATTACHMENT:
5349 break;
5350
5351 default:
5352 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
5353 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
5354 {
5355 context->handleError(Error(GL_INVALID_ENUM));
5356 return false;
5357 }
5358 break;
5359 }
5360
5361 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
5362 ASSERT(framebuffer);
5363
5364 if (framebuffer->id() == 0)
5365 {
5366 if (clientVersion < 3)
5367 {
5368 context->handleError(Error(GL_INVALID_OPERATION));
5369 return false;
5370 }
5371
5372 switch (attachment)
5373 {
5374 case GL_BACK:
5375 case GL_DEPTH:
5376 case GL_STENCIL:
5377 break;
5378
5379 default:
5380 context->handleError(Error(GL_INVALID_OPERATION));
5381 return false;
5382 }
5383 }
5384 else
5385 {
5386 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
5387 {
5388 // Valid attachment query
5389 }
5390 else
5391 {
5392 switch (attachment)
5393 {
5394 case GL_DEPTH_ATTACHMENT:
5395 case GL_STENCIL_ATTACHMENT:
5396 break;
5397
5398 case GL_DEPTH_STENCIL_ATTACHMENT:
5399 if (!framebuffer->hasValidDepthStencil())
5400 {
5401 context->handleError(Error(GL_INVALID_OPERATION));
5402 return false;
5403 }
5404 break;
5405
5406 default:
5407 context->handleError(Error(GL_INVALID_OPERATION));
5408 return false;
5409 }
5410 }
5411 }
5412
5413 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
5414 if (attachmentObject)
5415 {
5416 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
5417 attachmentObject->type() == GL_TEXTURE ||
5418 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
5419
5420 switch (pname)
5421 {
5422 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5423 if (attachmentObject->type() != GL_RENDERBUFFER &&
5424 attachmentObject->type() != GL_TEXTURE)
5425 {
5426 context->handleError(Error(GL_INVALID_ENUM));
5427 return false;
5428 }
5429 break;
5430
5431 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
5432 if (attachmentObject->type() != GL_TEXTURE)
5433 {
5434 context->handleError(Error(GL_INVALID_ENUM));
5435 return false;
5436 }
5437 break;
5438
5439 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
5440 if (attachmentObject->type() != GL_TEXTURE)
5441 {
5442 context->handleError(Error(GL_INVALID_ENUM));
5443 return false;
5444 }
5445 break;
5446
5447 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
5448 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
5449 {
5450 context->handleError(Error(GL_INVALID_OPERATION));
5451 return false;
5452 }
5453 break;
5454
5455 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
5456 if (attachmentObject->type() != GL_TEXTURE)
5457 {
5458 context->handleError(Error(GL_INVALID_ENUM));
5459 return false;
5460 }
5461 break;
5462
5463 default:
5464 break;
5465 }
5466 }
5467 else
5468 {
5469 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
5470 // is NONE, then querying any other pname will generate INVALID_ENUM.
5471
5472 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
5473 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
5474 // INVALID_OPERATION for all other pnames
5475
5476 switch (pname)
5477 {
5478 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5479 break;
5480
5481 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5482 if (clientVersion < 3)
5483 {
5484 context->handleError(Error(GL_INVALID_ENUM));
5485 return false;
5486 }
5487 break;
5488
5489 default:
5490 if (clientVersion < 3)
5491 {
5492 context->handleError(Error(GL_INVALID_ENUM));
5493 return false;
5494 }
5495 else
5496 {
5497 context->handleError(Error(GL_INVALID_OPERATION));
5498 return false;
5499 }
5500 }
5501 }
5502
5503 return true;
5504}
5505
5506bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5507 GLenum target,
5508 GLenum attachment,
5509 GLenum pname,
5510 GLsizei bufSize,
5511 GLsizei *numParams)
5512{
5513 if (!ValidateRobustEntryPoint(context, bufSize))
5514 {
5515 return false;
5516 }
5517
5518 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5519 {
5520 return false;
5521 }
5522
5523 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5524 {
5525 return false;
5526 }
5527
5528 return true;
5529}
5530
5531bool ValidateGetBufferParameteriv(ValidationContext *context,
5532 GLenum target,
5533 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005534 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005535{
Geoff Langebebe1c2016-10-14 12:01:31 -04005536 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005537}
5538
5539bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5540 GLenum target,
5541 GLenum pname,
5542 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005543 GLsizei *length,
5544 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005545{
5546 if (!ValidateRobustEntryPoint(context, bufSize))
5547 {
5548 return false;
5549 }
5550
Geoff Langebebe1c2016-10-14 12:01:31 -04005551 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005552 {
5553 return false;
5554 }
5555
Geoff Langebebe1c2016-10-14 12:01:31 -04005556 if (!ValidateRobustBufferSize(context, bufSize, *length))
5557 {
5558 return false;
5559 }
5560
5561 return true;
5562}
5563
5564bool ValidateGetBufferParameteri64v(ValidationContext *context,
5565 GLenum target,
5566 GLenum pname,
5567 GLint64 *params)
5568{
5569 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5570}
5571
5572bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5573 GLenum target,
5574 GLenum pname,
5575 GLsizei bufSize,
5576 GLsizei *length,
5577 GLint64 *params)
5578{
5579 if (!ValidateRobustEntryPoint(context, bufSize))
5580 {
5581 return false;
5582 }
5583
5584 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5585 {
5586 return false;
5587 }
5588
5589 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005590 {
5591 return false;
5592 }
5593
5594 return true;
5595}
5596
5597bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5598{
5599 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08005600 if (numParams)
5601 {
5602 *numParams = 1;
5603 }
Geoff Langff5b2d52016-09-07 11:32:23 -04005604
5605 Program *programObject = GetValidProgram(context, program);
5606 if (!programObject)
5607 {
5608 return false;
5609 }
5610
5611 switch (pname)
5612 {
5613 case GL_DELETE_STATUS:
5614 case GL_LINK_STATUS:
5615 case GL_VALIDATE_STATUS:
5616 case GL_INFO_LOG_LENGTH:
5617 case GL_ATTACHED_SHADERS:
5618 case GL_ACTIVE_ATTRIBUTES:
5619 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5620 case GL_ACTIVE_UNIFORMS:
5621 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5622 break;
5623
5624 case GL_PROGRAM_BINARY_LENGTH:
5625 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5626 {
5627 context->handleError(Error(GL_INVALID_ENUM,
5628 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5629 "GL_OES_get_program_binary or ES 3.0."));
5630 return false;
5631 }
5632 break;
5633
5634 case GL_ACTIVE_UNIFORM_BLOCKS:
5635 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5636 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5637 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5638 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5639 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5640 if (context->getClientMajorVersion() < 3)
5641 {
5642 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5643 return false;
5644 }
5645 break;
5646
Yunchao He61afff12017-03-14 15:34:03 +08005647 case GL_PROGRAM_SEPARABLE:
5648 if (context->getClientVersion() < Version(3, 1))
5649 {
5650 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.1."));
5651 return false;
5652 }
5653 break;
5654
Geoff Langff5b2d52016-09-07 11:32:23 -04005655 default:
5656 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5657 return false;
5658 }
5659
5660 return true;
5661}
5662
5663bool ValidateGetProgramivRobustANGLE(Context *context,
5664 GLuint program,
5665 GLenum pname,
5666 GLsizei bufSize,
5667 GLsizei *numParams)
5668{
5669 if (!ValidateRobustEntryPoint(context, bufSize))
5670 {
5671 return false;
5672 }
5673
5674 if (!ValidateGetProgramiv(context, program, pname, numParams))
5675 {
5676 return false;
5677 }
5678
5679 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5680 {
5681 return false;
5682 }
5683
5684 return true;
5685}
5686
Geoff Lang740d9022016-10-07 11:20:52 -04005687bool ValidateGetRenderbufferParameteriv(Context *context,
5688 GLenum target,
5689 GLenum pname,
5690 GLint *params)
5691{
5692 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5693}
5694
5695bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5696 GLenum target,
5697 GLenum pname,
5698 GLsizei bufSize,
5699 GLsizei *length,
5700 GLint *params)
5701{
5702 if (!ValidateRobustEntryPoint(context, bufSize))
5703 {
5704 return false;
5705 }
5706
5707 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5708 {
5709 return false;
5710 }
5711
5712 if (!ValidateRobustBufferSize(context, bufSize, *length))
5713 {
5714 return false;
5715 }
5716
5717 return true;
5718}
5719
Geoff Langd7d0ed32016-10-07 11:33:51 -04005720bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5721{
5722 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5723}
5724
5725bool ValidateGetShaderivRobustANGLE(Context *context,
5726 GLuint shader,
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 (!ValidateGetShaderivBase(context, shader, 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 Langc1984ed2016-10-07 12:41:00 -04005750bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5751{
5752 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5753}
5754
5755bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5756 GLenum target,
5757 GLenum pname,
5758 GLsizei bufSize,
5759 GLsizei *length,
5760 GLfloat *params)
5761{
5762 if (!ValidateRobustEntryPoint(context, bufSize))
5763 {
5764 return false;
5765 }
5766
5767 if (!ValidateGetTexParameterBase(context, target, 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
5780bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5781{
5782 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5783}
5784
5785bool ValidateGetTexParameterivRobustANGLE(Context *context,
5786 GLenum target,
5787 GLenum pname,
5788 GLsizei bufSize,
5789 GLsizei *length,
5790 GLint *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 ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5811{
5812 return ValidateTexParameterBase(context, target, pname, -1, &param);
5813}
5814
5815bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5816{
5817 return ValidateTexParameterBase(context, target, pname, -1, params);
5818}
5819
5820bool ValidateTexParameterfvRobustANGLE(Context *context,
5821 GLenum target,
5822 GLenum pname,
5823 GLsizei bufSize,
5824 const GLfloat *params)
5825{
5826 if (!ValidateRobustEntryPoint(context, bufSize))
5827 {
5828 return false;
5829 }
5830
5831 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5832}
5833
5834bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5835{
5836 return ValidateTexParameterBase(context, target, pname, -1, &param);
5837}
5838
5839bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5840{
5841 return ValidateTexParameterBase(context, target, pname, -1, params);
5842}
5843
5844bool ValidateTexParameterivRobustANGLE(Context *context,
5845 GLenum target,
5846 GLenum pname,
5847 GLsizei bufSize,
5848 const GLint *params)
5849{
5850 if (!ValidateRobustEntryPoint(context, bufSize))
5851 {
5852 return false;
5853 }
5854
5855 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5856}
5857
5858bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5859{
5860 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5861}
5862
5863bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5864 GLuint sampler,
5865 GLenum pname,
5866 GLuint bufSize,
5867 GLsizei *length,
5868 GLfloat *params)
5869{
5870 if (!ValidateRobustEntryPoint(context, bufSize))
5871 {
5872 return false;
5873 }
5874
5875 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5876 {
5877 return false;
5878 }
5879
5880 if (!ValidateRobustBufferSize(context, bufSize, *length))
5881 {
5882 return false;
5883 }
5884
5885 return true;
5886}
5887
5888bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5889{
5890 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5891}
5892
5893bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5894 GLuint sampler,
5895 GLenum pname,
5896 GLuint bufSize,
5897 GLsizei *length,
5898 GLint *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 ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5919{
5920 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5921}
5922
5923bool ValidateSamplerParameterfv(Context *context,
5924 GLuint sampler,
5925 GLenum pname,
5926 const GLfloat *params)
5927{
5928 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5929}
5930
5931bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5932 GLuint sampler,
5933 GLenum pname,
5934 GLsizei bufSize,
5935 const GLfloat *params)
5936{
5937 if (!ValidateRobustEntryPoint(context, bufSize))
5938 {
5939 return false;
5940 }
5941
5942 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5943}
5944
5945bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5946{
5947 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5948}
5949
5950bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5951{
5952 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5953}
5954
5955bool ValidateSamplerParameterivRobustANGLE(Context *context,
5956 GLuint sampler,
5957 GLenum pname,
5958 GLsizei bufSize,
5959 const GLint *params)
5960{
5961 if (!ValidateRobustEntryPoint(context, bufSize))
5962 {
5963 return false;
5964 }
5965
5966 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5967}
5968
Geoff Lang0b031062016-10-13 14:30:04 -04005969bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5970{
5971 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5972}
5973
5974bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5975 GLuint index,
5976 GLenum pname,
5977 GLsizei bufSize,
5978 GLsizei *length,
5979 GLfloat *params)
5980{
5981 if (!ValidateRobustEntryPoint(context, bufSize))
5982 {
5983 return false;
5984 }
5985
5986 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5987 {
5988 return false;
5989 }
5990
5991 if (!ValidateRobustBufferSize(context, bufSize, *length))
5992 {
5993 return false;
5994 }
5995
5996 return true;
5997}
5998
5999bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
6000{
6001 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6002}
6003
6004bool ValidateGetVertexAttribivRobustANGLE(Context *context,
6005 GLuint index,
6006 GLenum pname,
6007 GLsizei bufSize,
6008 GLsizei *length,
6009 GLint *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 ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
6030{
6031 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
6032}
6033
6034bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
6035 GLuint index,
6036 GLenum pname,
6037 GLsizei bufSize,
6038 GLsizei *length,
6039 void **pointer)
6040{
6041 if (!ValidateRobustEntryPoint(context, bufSize))
6042 {
6043 return false;
6044 }
6045
6046 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, 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 ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
6060{
6061 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
6062}
6063
6064bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
6065 GLuint index,
6066 GLenum pname,
6067 GLsizei bufSize,
6068 GLsizei *length,
6069 GLint *params)
6070{
6071 if (!ValidateRobustEntryPoint(context, bufSize))
6072 {
6073 return false;
6074 }
6075
6076 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
6077 {
6078 return false;
6079 }
6080
6081 if (!ValidateRobustBufferSize(context, bufSize, *length))
6082 {
6083 return false;
6084 }
6085
6086 return true;
6087}
6088
6089bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
6090{
6091 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
6092}
6093
6094bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
6095 GLuint index,
6096 GLenum pname,
6097 GLsizei bufSize,
6098 GLsizei *length,
6099 GLuint *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
Geoff Lang6899b872016-10-14 11:30:13 -04006119bool ValidateGetActiveUniformBlockiv(Context *context,
6120 GLuint program,
6121 GLuint uniformBlockIndex,
6122 GLenum pname,
6123 GLint *params)
6124{
6125 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
6126}
6127
6128bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
6129 GLuint program,
6130 GLuint uniformBlockIndex,
6131 GLenum pname,
6132 GLsizei bufSize,
6133 GLsizei *length,
6134 GLint *params)
6135{
6136 if (!ValidateRobustEntryPoint(context, bufSize))
6137 {
6138 return false;
6139 }
6140
6141 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
6142 {
6143 return false;
6144 }
6145
6146 if (!ValidateRobustBufferSize(context, bufSize, *length))
6147 {
6148 return false;
6149 }
6150
6151 return true;
6152}
6153
Geoff Lang0a9661f2016-10-20 10:59:20 -07006154bool ValidateGetInternalFormativ(Context *context,
6155 GLenum target,
6156 GLenum internalformat,
6157 GLenum pname,
6158 GLsizei bufSize,
6159 GLint *params)
6160{
6161 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
6162 nullptr);
6163}
6164
6165bool ValidateGetInternalFormativRobustANGLE(Context *context,
6166 GLenum target,
6167 GLenum internalformat,
6168 GLenum pname,
6169 GLsizei bufSize,
6170 GLsizei *length,
6171 GLint *params)
6172{
6173 if (!ValidateRobustEntryPoint(context, bufSize))
6174 {
6175 return false;
6176 }
6177
6178 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
6179 {
6180 return false;
6181 }
6182
6183 if (!ValidateRobustBufferSize(context, bufSize, *length))
6184 {
6185 return false;
6186 }
6187
6188 return true;
6189}
6190
Shao80957d92017-02-20 21:25:59 +08006191bool ValidateVertexFormatBase(ValidationContext *context,
6192 GLuint attribIndex,
6193 GLint size,
6194 GLenum type,
6195 GLboolean pureInteger)
6196{
6197 const Caps &caps = context->getCaps();
6198 if (attribIndex >= caps.maxVertexAttributes)
6199 {
6200 context->handleError(
6201 Error(GL_INVALID_VALUE, "attribindex must be smaller than MAX_VERTEX_ATTRIBS."));
6202 return false;
6203 }
6204
6205 if (size < 1 || size > 4)
6206 {
6207 context->handleError(Error(GL_INVALID_VALUE, "size must be between one and four."));
6208 }
6209
6210 switch (type)
6211 {
6212 case GL_BYTE:
6213 case GL_UNSIGNED_BYTE:
6214 case GL_SHORT:
6215 case GL_UNSIGNED_SHORT:
6216 break;
6217
6218 case GL_INT:
6219 case GL_UNSIGNED_INT:
6220 if (context->getClientMajorVersion() < 3)
6221 {
6222 context->handleError(
6223 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
6224 return false;
6225 }
6226 break;
6227
6228 case GL_FIXED:
6229 case GL_FLOAT:
6230 if (pureInteger)
6231 {
6232 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
6233 return false;
6234 }
6235 break;
6236
6237 case GL_HALF_FLOAT:
6238 if (context->getClientMajorVersion() < 3)
6239 {
6240 context->handleError(
6241 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
6242 return false;
6243 }
6244 if (pureInteger)
6245 {
6246 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
6247 return false;
6248 }
6249 break;
6250
6251 case GL_INT_2_10_10_10_REV:
6252 case GL_UNSIGNED_INT_2_10_10_10_REV:
6253 if (context->getClientMajorVersion() < 3)
6254 {
6255 context->handleError(
6256 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
6257 return false;
6258 }
6259 if (pureInteger)
6260 {
6261 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
6262 return false;
6263 }
6264 if (size != 4)
6265 {
6266 context->handleError(Error(GL_INVALID_OPERATION,
6267 "Type is INT_2_10_10_10_REV or "
6268 "UNSIGNED_INT_2_10_10_10_REV and size is not 4."));
6269 return false;
6270 }
6271 break;
6272
6273 default:
6274 context->handleError(Error(GL_INVALID_ENUM, "Invalid vertex type."));
6275 return false;
6276 }
6277
6278 return true;
6279}
6280
Geoff Lang76e65652017-03-27 14:58:02 -04006281// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
6282// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
6283// specified clear value and the type of a buffer that is being cleared generates an
6284// INVALID_OPERATION error instead of producing undefined results
6285bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
6286 GLint drawbuffer,
6287 const GLenum *validComponentTypes,
6288 size_t validComponentTypeCount)
6289{
6290 const FramebufferAttachment *attachment =
6291 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
6292 if (attachment)
6293 {
6294 GLenum componentType = attachment->getFormat().info->componentType;
6295 const GLenum *end = validComponentTypes + validComponentTypeCount;
6296 if (std::find(validComponentTypes, end, componentType) == end)
6297 {
6298 context->handleError(
6299 Error(GL_INVALID_OPERATION,
6300 "No defined conversion between clear value and attachment format."));
6301 return false;
6302 }
6303 }
6304
6305 return true;
6306}
6307
Corentin Wallezb2931602017-04-11 15:58:57 -04006308bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
6309 GLsizei imageSize,
6310 GLsizei dataSize)
6311{
6312 if (!ValidateRobustEntryPoint(context, dataSize))
6313 {
6314 return false;
6315 }
6316
6317 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
6318 if (pixelUnpackBuffer == nullptr)
6319 {
6320 if (dataSize < imageSize)
6321 {
6322 context->handleError(
6323 Error(GL_INVALID_OPERATION, "dataSize must be at least %i.", imageSize));
6324 }
6325 }
6326 return true;
6327}
6328
Jamie Madillc29968b2016-01-20 11:17:23 -05006329} // namespace gl