blob: c118d8a3f598d1376977061bace407e3c4b04a8e [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
Geoff Lang966c9402017-04-18 12:38:27 -04002139bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
2140{
2141 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
2142 (size % blockSize == 0);
2143}
2144
Jamie Madillc29968b2016-01-20 11:17:23 -05002145bool ValidCompressedImageSize(const ValidationContext *context,
2146 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -04002147 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -05002148 GLsizei width,
2149 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04002150{
Geoff Langca271392017-04-05 12:30:00 -04002151 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04002152 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04002153 {
2154 return false;
2155 }
2156
Geoff Lang966c9402017-04-18 12:38:27 -04002157 if (width < 0 || height < 0)
2158 {
2159 return false;
2160 }
2161
2162 if (CompressedTextureFormatRequiresExactSize(internalFormat))
2163 {
2164 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
2165 // block size for level 0 but WebGL disallows this.
2166 bool smallerThanBlockSizeAllowed =
2167 level > 0 || !context->getExtensions().webglCompatibility;
2168
2169 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
2170 smallerThanBlockSizeAllowed) ||
2171 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
2172 smallerThanBlockSizeAllowed))
2173 {
2174 return false;
2175 }
2176 }
2177
2178 return true;
2179}
2180
2181bool ValidCompressedSubImageSize(const ValidationContext *context,
2182 GLenum internalFormat,
2183 GLint xoffset,
2184 GLint yoffset,
2185 GLsizei width,
2186 GLsizei height,
2187 size_t textureWidth,
2188 size_t textureHeight)
2189{
2190 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
2191 if (!formatInfo.compressed)
2192 {
2193 return false;
2194 }
2195
Geoff Lang44ff5a72017-02-03 15:15:43 -05002196 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04002197 {
2198 return false;
2199 }
2200
Geoff Lang0d8b7242015-09-09 14:56:53 -04002201 if (CompressedTextureFormatRequiresExactSize(internalFormat))
2202 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05002203 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -04002204 yoffset % formatInfo.compressedBlockHeight != 0)
2205 {
2206 return false;
2207 }
2208
2209 // Allowed to either have data that is a multiple of block size or is smaller than the block
2210 // size but fills the entire mip
2211 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
2212 static_cast<size_t>(width) == textureWidth &&
2213 static_cast<size_t>(height) == textureHeight;
2214 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
2215 (height % formatInfo.compressedBlockHeight) == 0;
2216 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -04002217 {
2218 return false;
2219 }
2220 }
2221
Geoff Langd4f180b2013-09-24 13:57:44 -04002222 return true;
2223}
2224
Geoff Langff5b2d52016-09-07 11:32:23 -04002225bool ValidImageDataSize(ValidationContext *context,
2226 GLenum textureTarget,
2227 GLsizei width,
2228 GLsizei height,
2229 GLsizei depth,
2230 GLenum internalFormat,
2231 GLenum type,
2232 const GLvoid *pixels,
2233 GLsizei imageSize)
2234{
2235 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
2236 if (pixelUnpackBuffer == nullptr && imageSize < 0)
2237 {
2238 // Checks are not required
2239 return true;
2240 }
2241
2242 // ...the data would be unpacked from the buffer object such that the memory reads required
2243 // would exceed the data store size.
Geoff Langca271392017-04-05 12:30:00 -04002244 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
Geoff Langff5b2d52016-09-07 11:32:23 -04002245 const gl::Extents size(width, height, depth);
2246 const auto &unpack = context->getGLState().getUnpackState();
2247
2248 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
2249 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
2250 if (endByteOrErr.isError())
2251 {
2252 context->handleError(endByteOrErr.getError());
2253 return false;
2254 }
2255
2256 GLuint endByte = endByteOrErr.getResult();
2257
2258 if (pixelUnpackBuffer)
2259 {
2260 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
2261 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
2262 checkedEndByte += checkedOffset;
2263
2264 if (!checkedEndByte.IsValid() ||
2265 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
2266 {
2267 // Overflow past the end of the buffer
2268 context->handleError(Error(GL_INVALID_OPERATION));
2269 return false;
2270 }
2271 }
2272 else
2273 {
2274 ASSERT(imageSize >= 0);
2275 if (pixels == nullptr && imageSize != 0)
2276 {
2277 context->handleError(
2278 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04002279 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04002280 }
2281
Geoff Lang3feb3ff2016-10-26 10:57:45 -04002282 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04002283 {
2284 context->handleError(
2285 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
2286 return false;
2287 }
2288 }
2289
2290 return true;
2291}
2292
Geoff Lang37dde692014-01-31 16:34:54 -05002293bool ValidQueryType(const Context *context, GLenum queryType)
2294{
He Yunchaoced53ae2016-11-29 15:00:51 +08002295 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
2296 "GL extension enums not equal.");
2297 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2298 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05002299
2300 switch (queryType)
2301 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002302 case GL_ANY_SAMPLES_PASSED:
2303 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
2304 return true;
2305 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
2306 return (context->getClientMajorVersion() >= 3);
2307 case GL_TIME_ELAPSED_EXT:
2308 return context->getExtensions().disjointTimerQuery;
2309 case GL_COMMANDS_COMPLETED_CHROMIUM:
2310 return context->getExtensions().syncQuery;
2311 default:
2312 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05002313 }
2314}
2315
Geoff Lang2d62ab72017-03-23 16:54:40 -04002316bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
2317 GLenum type,
2318 GLboolean normalized,
2319 GLsizei stride,
2320 const GLvoid *ptr,
2321 bool pureInteger)
2322{
2323 ASSERT(context->getExtensions().webglCompatibility);
2324
2325 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
2326 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
2327 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
2328 // parameter exceeds 255.
2329 constexpr GLsizei kMaxWebGLStride = 255;
2330 if (stride > kMaxWebGLStride)
2331 {
2332 context->handleError(
2333 Error(GL_INVALID_VALUE, "Stride is over the maximum stride allowed by WebGL."));
2334 return false;
2335 }
2336
2337 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
2338 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
2339 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
2340 // or an INVALID_OPERATION error is generated.
2341 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
2342 size_t typeSize = GetVertexFormatTypeSize(internalType);
2343
2344 ASSERT(isPow2(typeSize) && typeSize > 0);
2345 size_t sizeMask = (typeSize - 1);
2346 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
2347 {
2348 context->handleError(
2349 Error(GL_INVALID_OPERATION, "Offset is not a multiple of the type size."));
2350 return false;
2351 }
2352
2353 if ((stride & sizeMask) != 0)
2354 {
2355 context->handleError(
2356 Error(GL_INVALID_OPERATION, "Stride is not a multiple of the type size."));
2357 return false;
2358 }
2359
2360 return true;
2361}
2362
Jamie Madillef300b12016-10-07 15:12:09 -04002363Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05002364{
He Yunchaoced53ae2016-11-29 15:00:51 +08002365 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
2366 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
2367 // or program object and INVALID_OPERATION if the provided name identifies an object
2368 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05002369
Dian Xiang769769a2015-09-09 15:20:08 -07002370 Program *validProgram = context->getProgram(id);
2371
2372 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05002373 {
Dian Xiang769769a2015-09-09 15:20:08 -07002374 if (context->getShader(id))
2375 {
Jamie Madill437fa652016-05-03 15:13:24 -04002376 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07002377 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
2378 }
2379 else
2380 {
Jamie Madill437fa652016-05-03 15:13:24 -04002381 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07002382 }
Geoff Lang48dcae72014-02-05 16:28:24 -05002383 }
Dian Xiang769769a2015-09-09 15:20:08 -07002384
2385 return validProgram;
2386}
2387
Jamie Madillef300b12016-10-07 15:12:09 -04002388Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07002389{
2390 // See ValidProgram for spec details.
2391
2392 Shader *validShader = context->getShader(id);
2393
2394 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05002395 {
Dian Xiang769769a2015-09-09 15:20:08 -07002396 if (context->getProgram(id))
2397 {
Jamie Madill437fa652016-05-03 15:13:24 -04002398 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07002399 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
2400 }
2401 else
2402 {
Jamie Madill437fa652016-05-03 15:13:24 -04002403 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07002404 }
Geoff Lang48dcae72014-02-05 16:28:24 -05002405 }
Dian Xiang769769a2015-09-09 15:20:08 -07002406
2407 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05002408}
2409
Geoff Langb1196682014-07-23 13:47:29 -04002410bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04002411{
2412 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
2413 {
2414 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
2415
Geoff Langaae65a42014-05-26 12:43:44 -04002416 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04002417 {
Jamie Madill437fa652016-05-03 15:13:24 -04002418 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002419 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04002420 }
2421 }
2422 else
2423 {
2424 switch (attachment)
2425 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002426 case GL_DEPTH_ATTACHMENT:
2427 case GL_STENCIL_ATTACHMENT:
2428 break;
Jamie Madillb4472272014-07-03 10:38:55 -04002429
He Yunchaoced53ae2016-11-29 15:00:51 +08002430 case GL_DEPTH_STENCIL_ATTACHMENT:
2431 if (!context->getExtensions().webglCompatibility &&
2432 context->getClientMajorVersion() < 3)
2433 {
2434 context->handleError(Error(GL_INVALID_ENUM));
2435 return false;
2436 }
2437 break;
Jamie Madillb4472272014-07-03 10:38:55 -04002438
He Yunchaoced53ae2016-11-29 15:00:51 +08002439 default:
2440 context->handleError(Error(GL_INVALID_ENUM));
2441 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04002442 }
2443 }
2444
2445 return true;
2446}
2447
Jamie Madille8fb6402017-02-14 17:56:40 -05002448bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08002449 GLenum target,
2450 GLsizei samples,
2451 GLenum internalformat,
2452 GLsizei width,
2453 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002454{
2455 switch (target)
2456 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002457 case GL_RENDERBUFFER:
2458 break;
2459 default:
2460 context->handleError(Error(GL_INVALID_ENUM));
2461 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002462 }
2463
2464 if (width < 0 || height < 0 || samples < 0)
2465 {
Jamie Madill437fa652016-05-03 15:13:24 -04002466 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002467 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002468 }
2469
Jamie Madill4e0e6f82017-02-17 11:06:03 -05002470 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
2471 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
2472
2473 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04002474 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002475 {
Jamie Madill437fa652016-05-03 15:13:24 -04002476 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002477 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002478 }
2479
2480 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
2481 // 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 -08002482 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04002483 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
2484 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002485 {
Jamie Madill437fa652016-05-03 15:13:24 -04002486 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002487 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002488 }
2489
Geoff Langaae65a42014-05-26 12:43:44 -04002490 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002491 {
Jamie Madill437fa652016-05-03 15:13:24 -04002492 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002493 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002494 }
2495
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002496 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002497 if (handle == 0)
2498 {
Jamie Madill437fa652016-05-03 15:13:24 -04002499 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002500 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002501 }
2502
2503 return true;
2504}
2505
He Yunchaoced53ae2016-11-29 15:00:51 +08002506bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
2507 GLenum target,
2508 GLenum attachment,
2509 GLenum renderbuffertarget,
2510 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002511{
Shannon Woods1da3cf62014-06-27 15:32:23 -04002512 if (!ValidFramebufferTarget(target))
2513 {
Jamie Madill437fa652016-05-03 15:13:24 -04002514 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002515 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04002516 }
2517
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002518 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002519
Jamie Madill84115c92015-04-23 15:00:07 -04002520 ASSERT(framebuffer);
2521 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002522 {
Jamie Madill437fa652016-05-03 15:13:24 -04002523 context->handleError(
2524 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002525 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002526 }
2527
Jamie Madillb4472272014-07-03 10:38:55 -04002528 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002529 {
Jamie Madillb4472272014-07-03 10:38:55 -04002530 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002531 }
2532
Jamie Madillab9d82c2014-01-21 16:38:14 -05002533 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2534 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2535 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2536 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2537 if (renderbuffer != 0)
2538 {
2539 if (!context->getRenderbuffer(renderbuffer))
2540 {
Jamie Madill437fa652016-05-03 15:13:24 -04002541 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002542 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05002543 }
2544 }
2545
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002546 return true;
2547}
2548
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002549bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002550 GLint srcX0,
2551 GLint srcY0,
2552 GLint srcX1,
2553 GLint srcY1,
2554 GLint dstX0,
2555 GLint dstY0,
2556 GLint dstX1,
2557 GLint dstY1,
2558 GLbitfield mask,
2559 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002560{
2561 switch (filter)
2562 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002563 case GL_NEAREST:
2564 break;
2565 case GL_LINEAR:
2566 break;
2567 default:
2568 context->handleError(Error(GL_INVALID_ENUM));
2569 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002570 }
2571
2572 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
2573 {
Jamie Madill437fa652016-05-03 15:13:24 -04002574 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002575 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002576 }
2577
2578 if (mask == 0)
2579 {
2580 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
2581 // buffers are copied.
2582 return false;
2583 }
2584
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002585 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
2586 // color buffer, leaving only nearest being unfiltered from above
2587 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
2588 {
Jamie Madill437fa652016-05-03 15:13:24 -04002589 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002590 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002591 }
2592
Jamie Madill51f40ec2016-06-15 14:06:00 -04002593 const auto &glState = context->getGLState();
2594 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2595 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05002596
2597 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002598 {
Jamie Madill437fa652016-05-03 15:13:24 -04002599 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002600 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002601 }
2602
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002603 if (readFramebuffer->id() == drawFramebuffer->id())
2604 {
2605 context->handleError(Error(GL_INVALID_OPERATION));
2606 return false;
2607 }
2608
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002609 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002610 {
Jamie Madill437fa652016-05-03 15:13:24 -04002611 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002612 return false;
2613 }
2614
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002615 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002616 {
Jamie Madill437fa652016-05-03 15:13:24 -04002617 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002618 return false;
2619 }
2620
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002621 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002622 {
Jamie Madill437fa652016-05-03 15:13:24 -04002623 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002624 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002625 }
2626
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002627 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2628
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002629 if (mask & GL_COLOR_BUFFER_BIT)
2630 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002631 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002632 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002633
He Yunchao66a41a22016-12-15 16:45:05 +08002634 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002635 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002636 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002637
Geoff Langa15472a2015-08-11 11:48:03 -04002638 for (size_t drawbufferIdx = 0;
2639 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002640 {
Geoff Langa15472a2015-08-11 11:48:03 -04002641 const FramebufferAttachment *attachment =
2642 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2643 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002644 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002645 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002646
Geoff Langb2f3d052013-08-13 12:49:27 -04002647 // The GL ES 3.0.2 spec (pg 193) states that:
2648 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002649 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2650 // as well
2651 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2652 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002653 // Changes with EXT_color_buffer_float:
2654 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002655 GLenum readComponentType = readFormat.info->componentType;
2656 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002657 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002658 readComponentType == GL_SIGNED_NORMALIZED);
2659 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2660 drawComponentType == GL_SIGNED_NORMALIZED);
2661
2662 if (extensions.colorBufferFloat)
2663 {
2664 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2665 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2666
2667 if (readFixedOrFloat != drawFixedOrFloat)
2668 {
Jamie Madill437fa652016-05-03 15:13:24 -04002669 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002670 "If the read buffer contains fixed-point or "
2671 "floating-point values, the draw buffer "
2672 "must as well."));
2673 return false;
2674 }
2675 }
2676 else if (readFixedPoint != drawFixedPoint)
2677 {
Jamie Madill437fa652016-05-03 15:13:24 -04002678 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002679 "If the read buffer contains fixed-point "
2680 "values, the draw buffer must as well."));
2681 return false;
2682 }
2683
2684 if (readComponentType == GL_UNSIGNED_INT &&
2685 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002686 {
Jamie Madill437fa652016-05-03 15:13:24 -04002687 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002688 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002689 }
2690
Jamie Madill6163c752015-12-07 16:32:59 -05002691 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002692 {
Jamie Madill437fa652016-05-03 15:13:24 -04002693 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002694 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002695 }
2696
Jamie Madilla3944d42016-07-22 22:13:26 -04002697 if (readColorBuffer->getSamples() > 0 &&
2698 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002699 {
Jamie Madill437fa652016-05-03 15:13:24 -04002700 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002701 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002702 }
Geoff Lange4915782017-04-12 15:19:07 -04002703
2704 if (context->getExtensions().webglCompatibility &&
2705 *readColorBuffer == *attachment)
2706 {
2707 context->handleError(
2708 Error(GL_INVALID_OPERATION,
2709 "Read and write color attachments cannot be the same image."));
2710 return false;
2711 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002712 }
2713 }
2714
Jamie Madilla3944d42016-07-22 22:13:26 -04002715 if ((readFormat.info->componentType == GL_INT ||
2716 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2717 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002718 {
Jamie Madill437fa652016-05-03 15:13:24 -04002719 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002720 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002721 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002722 }
He Yunchao66a41a22016-12-15 16:45:05 +08002723 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2724 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2725 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2726 // situation is an application error that would lead to a crash in ANGLE.
2727 else if (drawFramebuffer->hasEnabledDrawBuffer())
2728 {
2729 context->handleError(Error(
2730 GL_INVALID_OPERATION,
2731 "Attempt to read from a missing color attachment of a complete framebuffer."));
2732 return false;
2733 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002734 }
2735
He Yunchaoced53ae2016-11-29 15:00:51 +08002736 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002737 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2738 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002739 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002740 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002741 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002742 const gl::FramebufferAttachment *readBuffer =
2743 readFramebuffer->getAttachment(attachments[i]);
2744 const gl::FramebufferAttachment *drawBuffer =
2745 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002746
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002747 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002748 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002749 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002750 {
Jamie Madill437fa652016-05-03 15:13:24 -04002751 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002752 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002753 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002754
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002755 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002756 {
Jamie Madill437fa652016-05-03 15:13:24 -04002757 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002758 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002759 }
Geoff Lange4915782017-04-12 15:19:07 -04002760
2761 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
2762 {
2763 context->handleError(Error(
2764 GL_INVALID_OPERATION,
2765 "Read and write depth stencil attachments cannot be the same image."));
2766 return false;
2767 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002768 }
He Yunchao66a41a22016-12-15 16:45:05 +08002769 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2770 else if (drawBuffer)
2771 {
2772 context->handleError(Error(GL_INVALID_OPERATION,
2773 "Attempt to read from a missing depth/stencil "
2774 "attachment of a complete framebuffer."));
2775 return false;
2776 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002777 }
2778 }
2779
2780 return true;
2781}
2782
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002783bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002784 GLint x,
2785 GLint y,
2786 GLsizei width,
2787 GLsizei height,
2788 GLenum format,
2789 GLenum type,
2790 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002791{
Geoff Lange93daba2017-03-30 13:54:40 -04002792 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
2793 nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04002794}
2795
2796bool ValidateReadPixelsRobustANGLE(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 *pixels)
2808{
2809 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002810 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002811 return false;
2812 }
2813
Geoff Lang62fce5b2016-09-30 10:46:35 -04002814 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04002815 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002816 {
Geoff Langb1196682014-07-23 13:47:29 -04002817 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002818 }
2819
Geoff Lang62fce5b2016-09-30 10:46:35 -04002820 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002821 {
Geoff Langb1196682014-07-23 13:47:29 -04002822 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002823 }
2824
Jamie Madillc29968b2016-01-20 11:17:23 -05002825 return true;
2826}
2827
2828bool ValidateReadnPixelsEXT(Context *context,
2829 GLint x,
2830 GLint y,
2831 GLsizei width,
2832 GLsizei height,
2833 GLenum format,
2834 GLenum type,
2835 GLsizei bufSize,
2836 GLvoid *pixels)
2837{
2838 if (bufSize < 0)
2839 {
Jamie Madill437fa652016-05-03 15:13:24 -04002840 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002841 return false;
2842 }
2843
Geoff Lang62fce5b2016-09-30 10:46:35 -04002844 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04002845 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04002846}
Jamie Madill26e91952014-03-05 15:01:27 -05002847
Geoff Lang62fce5b2016-09-30 10:46:35 -04002848bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2849 GLint x,
2850 GLint y,
2851 GLsizei width,
2852 GLsizei height,
2853 GLenum format,
2854 GLenum type,
2855 GLsizei bufSize,
2856 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04002857 GLsizei *columns,
2858 GLsizei *rows,
Geoff Lang62fce5b2016-09-30 10:46:35 -04002859 GLvoid *data)
2860{
2861 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002862 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002863 return false;
2864 }
2865
Geoff Lange93daba2017-03-30 13:54:40 -04002866 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2867 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002868 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002869 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002870 }
2871
Geoff Lang62fce5b2016-09-30 10:46:35 -04002872 if (!ValidateRobustBufferSize(context, bufSize, *length))
2873 {
2874 return false;
2875 }
2876
2877 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002878}
2879
Olli Etuaho41997e72016-03-10 13:38:39 +02002880bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002881{
2882 if (!context->getExtensions().occlusionQueryBoolean &&
2883 !context->getExtensions().disjointTimerQuery)
2884 {
Jamie Madill437fa652016-05-03 15:13:24 -04002885 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002886 return false;
2887 }
2888
Olli Etuaho41997e72016-03-10 13:38:39 +02002889 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002890}
2891
Olli Etuaho41997e72016-03-10 13:38:39 +02002892bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002893{
2894 if (!context->getExtensions().occlusionQueryBoolean &&
2895 !context->getExtensions().disjointTimerQuery)
2896 {
Jamie Madill437fa652016-05-03 15:13:24 -04002897 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002898 return false;
2899 }
2900
Olli Etuaho41997e72016-03-10 13:38:39 +02002901 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002902}
2903
2904bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002905{
2906 if (!ValidQueryType(context, target))
2907 {
Jamie Madill437fa652016-05-03 15:13:24 -04002908 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002909 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002910 }
2911
2912 if (id == 0)
2913 {
Jamie Madill437fa652016-05-03 15:13:24 -04002914 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002915 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002916 }
2917
2918 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2919 // of zero, if the active query object name for <target> is non-zero (for the
2920 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2921 // the active query for either target is non-zero), if <id> is the name of an
2922 // existing query object whose type does not match <target>, or if <id> is the
2923 // active query object name for any query type, the error INVALID_OPERATION is
2924 // generated.
2925
2926 // Ensure no other queries are active
2927 // NOTE: If other queries than occlusion are supported, we will need to check
2928 // separately that:
2929 // a) The query ID passed is not the current active query for any target/type
2930 // b) There are no active queries for the requested target (and in the case
2931 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2932 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002933
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002934 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002935 {
Jamie Madill437fa652016-05-03 15:13:24 -04002936 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002937 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002938 }
2939
2940 Query *queryObject = context->getQuery(id, true, target);
2941
2942 // check that name was obtained with glGenQueries
2943 if (!queryObject)
2944 {
Jamie Madill437fa652016-05-03 15:13:24 -04002945 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002946 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002947 }
2948
2949 // check for type mismatch
2950 if (queryObject->getType() != target)
2951 {
Jamie Madill437fa652016-05-03 15:13:24 -04002952 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002953 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002954 }
2955
2956 return true;
2957}
2958
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002959bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2960{
2961 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002962 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002963 {
Jamie Madill437fa652016-05-03 15:13:24 -04002964 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002965 return false;
2966 }
2967
2968 return ValidateBeginQueryBase(context, target, id);
2969}
2970
2971bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002972{
2973 if (!ValidQueryType(context, target))
2974 {
Jamie Madill437fa652016-05-03 15:13:24 -04002975 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002976 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002977 }
2978
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002979 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002980
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002981 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002982 {
Jamie Madill437fa652016-05-03 15:13:24 -04002983 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002984 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002985 }
2986
Jamie Madill45c785d2014-05-13 14:09:34 -04002987 return true;
2988}
2989
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002990bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2991{
2992 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002993 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002994 {
Jamie Madill437fa652016-05-03 15:13:24 -04002995 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002996 return false;
2997 }
2998
2999 return ValidateEndQueryBase(context, target);
3000}
3001
3002bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
3003{
3004 if (!context->getExtensions().disjointTimerQuery)
3005 {
Jamie Madill437fa652016-05-03 15:13:24 -04003006 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003007 return false;
3008 }
3009
3010 if (target != GL_TIMESTAMP_EXT)
3011 {
Jamie Madill437fa652016-05-03 15:13:24 -04003012 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003013 return false;
3014 }
3015
3016 Query *queryObject = context->getQuery(id, true, target);
3017 if (queryObject == nullptr)
3018 {
Jamie Madill437fa652016-05-03 15:13:24 -04003019 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003020 return false;
3021 }
3022
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003023 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003024 {
Jamie Madill437fa652016-05-03 15:13:24 -04003025 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003026 return false;
3027 }
3028
3029 return true;
3030}
3031
Geoff Lang2186c382016-10-14 10:54:54 -04003032bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003033{
Geoff Lang2186c382016-10-14 10:54:54 -04003034 if (numParams)
3035 {
3036 *numParams = 0;
3037 }
3038
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003039 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
3040 {
Jamie Madill437fa652016-05-03 15:13:24 -04003041 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003042 return false;
3043 }
3044
3045 switch (pname)
3046 {
3047 case GL_CURRENT_QUERY_EXT:
3048 if (target == GL_TIMESTAMP_EXT)
3049 {
Jamie Madill437fa652016-05-03 15:13:24 -04003050 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003051 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
3052 return false;
3053 }
3054 break;
3055 case GL_QUERY_COUNTER_BITS_EXT:
3056 if (!context->getExtensions().disjointTimerQuery ||
3057 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
3058 {
Jamie Madill437fa652016-05-03 15:13:24 -04003059 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003060 return false;
3061 }
3062 break;
3063 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003064 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003065 return false;
3066 }
3067
Geoff Lang2186c382016-10-14 10:54:54 -04003068 if (numParams)
3069 {
3070 // All queries return only one value
3071 *numParams = 1;
3072 }
3073
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003074 return true;
3075}
3076
3077bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
3078{
3079 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04003080 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003081 {
Jamie Madill437fa652016-05-03 15:13:24 -04003082 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003083 return false;
3084 }
3085
Geoff Lang2186c382016-10-14 10:54:54 -04003086 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003087}
3088
Geoff Lang2186c382016-10-14 10:54:54 -04003089bool ValidateGetQueryivRobustANGLE(Context *context,
3090 GLenum target,
3091 GLenum pname,
3092 GLsizei bufSize,
3093 GLsizei *length,
3094 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003095{
Geoff Lang2186c382016-10-14 10:54:54 -04003096 if (!ValidateRobustEntryPoint(context, bufSize))
3097 {
3098 return false;
3099 }
3100
3101 if (!ValidateGetQueryivBase(context, target, pname, length))
3102 {
3103 return false;
3104 }
3105
3106 if (!ValidateRobustBufferSize(context, bufSize, *length))
3107 {
3108 return false;
3109 }
3110
3111 return true;
3112}
3113
3114bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
3115{
3116 if (numParams)
3117 {
3118 *numParams = 0;
3119 }
3120
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003121 Query *queryObject = context->getQuery(id, false, GL_NONE);
3122
3123 if (!queryObject)
3124 {
Jamie Madill437fa652016-05-03 15:13:24 -04003125 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003126 return false;
3127 }
3128
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003129 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003130 {
Jamie Madill437fa652016-05-03 15:13:24 -04003131 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003132 return false;
3133 }
3134
3135 switch (pname)
3136 {
3137 case GL_QUERY_RESULT_EXT:
3138 case GL_QUERY_RESULT_AVAILABLE_EXT:
3139 break;
3140
3141 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003142 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003143 return false;
3144 }
3145
Geoff Lang2186c382016-10-14 10:54:54 -04003146 if (numParams)
3147 {
3148 *numParams = 1;
3149 }
3150
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003151 return true;
3152}
3153
3154bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
3155{
3156 if (!context->getExtensions().disjointTimerQuery)
3157 {
Jamie Madill437fa652016-05-03 15:13:24 -04003158 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003159 return false;
3160 }
Geoff Lang2186c382016-10-14 10:54:54 -04003161 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
3162}
3163
3164bool ValidateGetQueryObjectivRobustANGLE(Context *context,
3165 GLuint id,
3166 GLenum pname,
3167 GLsizei bufSize,
3168 GLsizei *length,
3169 GLint *params)
3170{
3171 if (!context->getExtensions().disjointTimerQuery)
3172 {
3173 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
3174 return false;
3175 }
3176
3177 if (!ValidateRobustEntryPoint(context, bufSize))
3178 {
3179 return false;
3180 }
3181
3182 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
3183 {
3184 return false;
3185 }
3186
3187 if (!ValidateRobustBufferSize(context, bufSize, *length))
3188 {
3189 return false;
3190 }
3191
3192 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003193}
3194
3195bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
3196{
3197 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04003198 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003199 {
Jamie Madill437fa652016-05-03 15:13:24 -04003200 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003201 return false;
3202 }
Geoff Lang2186c382016-10-14 10:54:54 -04003203 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
3204}
3205
3206bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
3207 GLuint id,
3208 GLenum pname,
3209 GLsizei bufSize,
3210 GLsizei *length,
3211 GLuint *params)
3212{
3213 if (!context->getExtensions().disjointTimerQuery &&
3214 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
3215 {
3216 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
3217 return false;
3218 }
3219
3220 if (!ValidateRobustEntryPoint(context, bufSize))
3221 {
3222 return false;
3223 }
3224
3225 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
3226 {
3227 return false;
3228 }
3229
3230 if (!ValidateRobustBufferSize(context, bufSize, *length))
3231 {
3232 return false;
3233 }
3234
3235 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003236}
3237
3238bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
3239{
3240 if (!context->getExtensions().disjointTimerQuery)
3241 {
Jamie Madill437fa652016-05-03 15:13:24 -04003242 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003243 return false;
3244 }
Geoff Lang2186c382016-10-14 10:54:54 -04003245 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
3246}
3247
3248bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
3249 GLuint id,
3250 GLenum pname,
3251 GLsizei bufSize,
3252 GLsizei *length,
3253 GLint64 *params)
3254{
3255 if (!context->getExtensions().disjointTimerQuery)
3256 {
3257 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
3258 return false;
3259 }
3260
3261 if (!ValidateRobustEntryPoint(context, bufSize))
3262 {
3263 return false;
3264 }
3265
3266 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
3267 {
3268 return false;
3269 }
3270
3271 if (!ValidateRobustBufferSize(context, bufSize, *length))
3272 {
3273 return false;
3274 }
3275
3276 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003277}
3278
3279bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
3280{
3281 if (!context->getExtensions().disjointTimerQuery)
3282 {
Jamie Madill437fa652016-05-03 15:13:24 -04003283 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003284 return false;
3285 }
Geoff Lang2186c382016-10-14 10:54:54 -04003286 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
3287}
3288
3289bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
3290 GLuint id,
3291 GLenum pname,
3292 GLsizei bufSize,
3293 GLsizei *length,
3294 GLuint64 *params)
3295{
3296 if (!context->getExtensions().disjointTimerQuery)
3297 {
3298 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
3299 return false;
3300 }
3301
3302 if (!ValidateRobustEntryPoint(context, bufSize))
3303 {
3304 return false;
3305 }
3306
3307 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
3308 {
3309 return false;
3310 }
3311
3312 if (!ValidateRobustBufferSize(context, bufSize, *length))
3313 {
3314 return false;
3315 }
3316
3317 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05003318}
3319
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003320bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003321 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003322 GLuint program,
3323 GLint location,
3324 GLsizei count)
3325{
3326 // Check for ES31 program uniform entry points
3327 if (context->getClientVersion() < Version(3, 1))
3328 {
3329 context->handleError(Error(GL_INVALID_OPERATION));
3330 return false;
3331 }
3332
3333 const LinkedUniform *uniform = nullptr;
3334 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003335 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3336 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003337}
3338
Frank Henigmana98a6472017-02-02 21:38:32 -05003339bool ValidateProgramUniform1iv(gl::Context *context,
3340 GLuint program,
3341 GLint location,
3342 GLsizei count,
3343 const GLint *value)
3344{
3345 // Check for ES31 program uniform entry points
3346 if (context->getClientVersion() < Version(3, 1))
3347 {
3348 context->handleError(Error(GL_INVALID_OPERATION));
3349 return false;
3350 }
3351
3352 const LinkedUniform *uniform = nullptr;
3353 gl::Program *programObject = GetValidProgram(context, program);
3354 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3355 ValidateUniform1ivValue(context, uniform->type, count, value);
3356}
3357
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003358bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003359 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003360 GLuint program,
3361 GLint location,
3362 GLsizei count,
3363 GLboolean transpose)
3364{
3365 // Check for ES31 program uniform entry points
3366 if (context->getClientVersion() < Version(3, 1))
3367 {
3368 context->handleError(Error(GL_INVALID_OPERATION));
3369 return false;
3370 }
3371
3372 const LinkedUniform *uniform = nullptr;
3373 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003374 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3375 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08003376}
3377
Jamie Madillc1d770e2017-04-13 17:31:24 -04003378bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04003379{
3380 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003381 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04003382 {
Jamie Madill437fa652016-05-03 15:13:24 -04003383 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003384 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04003385 }
3386
Jamie Madill62d31cb2015-09-11 13:25:51 -04003387 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003388 gl::Program *programObject = context->getGLState().getProgram();
3389 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3390 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04003391}
3392
Frank Henigmana98a6472017-02-02 21:38:32 -05003393bool ValidateUniform1iv(gl::Context *context, GLint location, GLsizei count, const GLint *value)
3394{
3395 const LinkedUniform *uniform = nullptr;
3396 gl::Program *programObject = context->getGLState().getProgram();
3397 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3398 ValidateUniform1ivValue(context, uniform->type, count, value);
3399}
3400
Jamie Madillc1d770e2017-04-13 17:31:24 -04003401bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003402 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08003403 GLint location,
3404 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04003405 GLboolean transpose)
3406{
3407 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003408 int rows = VariableRowCount(valueType);
3409 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03003410 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04003411 {
Jamie Madill437fa652016-05-03 15:13:24 -04003412 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003413 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04003414 }
3415
Martin Radev1be913c2016-07-11 17:59:16 +03003416 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04003417 {
Jamie Madill437fa652016-05-03 15:13:24 -04003418 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003419 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04003420 }
3421
Jamie Madill62d31cb2015-09-11 13:25:51 -04003422 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05003423 gl::Program *programObject = context->getGLState().getProgram();
3424 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
3425 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04003426}
3427
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003428bool ValidateStateQuery(ValidationContext *context,
3429 GLenum pname,
3430 GLenum *nativeType,
3431 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04003432{
3433 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
3434 {
Jamie Madill437fa652016-05-03 15:13:24 -04003435 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003436 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003437 }
3438
Jamie Madill0af26e12015-03-05 19:54:33 -05003439 const Caps &caps = context->getCaps();
3440
Jamie Madill893ab082014-05-16 16:56:10 -04003441 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
3442 {
3443 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
3444
Jamie Madill0af26e12015-03-05 19:54:33 -05003445 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04003446 {
Jamie Madill437fa652016-05-03 15:13:24 -04003447 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003448 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003449 }
3450 }
3451
3452 switch (pname)
3453 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003454 case GL_TEXTURE_BINDING_2D:
3455 case GL_TEXTURE_BINDING_CUBE_MAP:
3456 case GL_TEXTURE_BINDING_3D:
3457 case GL_TEXTURE_BINDING_2D_ARRAY:
3458 break;
3459 case GL_TEXTURE_BINDING_EXTERNAL_OES:
3460 if (!context->getExtensions().eglStreamConsumerExternal &&
3461 !context->getExtensions().eglImageExternal)
3462 {
3463 context->handleError(Error(GL_INVALID_ENUM,
3464 "Neither NV_EGL_stream_consumer_external nor "
3465 "GL_OES_EGL_image_external extensions enabled"));
3466 return false;
3467 }
3468 break;
Jamie Madill893ab082014-05-16 16:56:10 -04003469
He Yunchaoced53ae2016-11-29 15:00:51 +08003470 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
3471 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04003472 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04003473 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
3474 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04003475 {
Jamie Madill437fa652016-05-03 15:13:24 -04003476 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003477 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003478 }
3479
Jamie Madill51f40ec2016-06-15 14:06:00 -04003480 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
3481 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03003482
3483 if (framebuffer->getReadBufferState() == GL_NONE)
3484 {
3485 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3486 return false;
3487 }
3488
Jamie Madillb6bda4a2015-04-20 12:53:26 -04003489 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04003490 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04003491 {
Jamie Madill437fa652016-05-03 15:13:24 -04003492 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003493 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04003494 }
3495 }
3496 break;
3497
He Yunchaoced53ae2016-11-29 15:00:51 +08003498 default:
3499 break;
Jamie Madill893ab082014-05-16 16:56:10 -04003500 }
3501
3502 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04003503 if (*numParams == 0)
3504 {
3505 return false;
3506 }
3507
3508 return true;
3509}
3510
3511bool ValidateRobustStateQuery(ValidationContext *context,
3512 GLenum pname,
3513 GLsizei bufSize,
3514 GLenum *nativeType,
3515 unsigned int *numParams)
3516{
3517 if (!ValidateRobustEntryPoint(context, bufSize))
3518 {
3519 return false;
3520 }
3521
3522 if (!ValidateStateQuery(context, pname, nativeType, numParams))
3523 {
3524 return false;
3525 }
3526
3527 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04003528 {
3529 return false;
3530 }
3531
3532 return true;
3533}
3534
Jamie Madillc29968b2016-01-20 11:17:23 -05003535bool ValidateCopyTexImageParametersBase(ValidationContext *context,
3536 GLenum target,
3537 GLint level,
3538 GLenum internalformat,
3539 bool isSubImage,
3540 GLint xoffset,
3541 GLint yoffset,
3542 GLint zoffset,
3543 GLint x,
3544 GLint y,
3545 GLsizei width,
3546 GLsizei height,
3547 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04003548 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04003549{
Jamie Madill560a8d82014-05-21 13:06:20 -04003550 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
3551 {
Jamie Madill437fa652016-05-03 15:13:24 -04003552 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003553 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003554 }
3555
He Yunchaoced53ae2016-11-29 15:00:51 +08003556 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3557 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04003558 {
Jamie Madill437fa652016-05-03 15:13:24 -04003559 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003560 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003561 }
3562
3563 if (border != 0)
3564 {
Jamie Madill437fa652016-05-03 15:13:24 -04003565 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003566 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003567 }
3568
3569 if (!ValidMipLevel(context, target, level))
3570 {
Jamie Madill437fa652016-05-03 15:13:24 -04003571 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003572 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003573 }
3574
Jamie Madill51f40ec2016-06-15 14:06:00 -04003575 const auto &state = context->getGLState();
3576 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04003577 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003578 {
Jamie Madill437fa652016-05-03 15:13:24 -04003579 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003580 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003581 }
3582
Jamie Madilldd43e6c2017-03-24 14:18:49 -04003583 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003584 {
Jamie Madill437fa652016-05-03 15:13:24 -04003585 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003586 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003587 }
3588
Martin Radev138064f2016-07-15 12:03:41 +03003589 if (readFramebuffer->getReadBufferState() == GL_NONE)
3590 {
3591 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3592 return false;
3593 }
3594
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003595 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3596 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003597 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003598 // situation is an application error that would lead to a crash in ANGLE.
3599 if (readFramebuffer->getReadColorbuffer() == nullptr)
3600 {
3601 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3602 return false;
3603 }
3604
Geoff Langaae65a42014-05-26 12:43:44 -04003605 const gl::Caps &caps = context->getCaps();
3606
Geoff Langaae65a42014-05-26 12:43:44 -04003607 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003608 switch (target)
3609 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003610 case GL_TEXTURE_2D:
3611 maxDimension = caps.max2DTextureSize;
3612 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003613
He Yunchaoced53ae2016-11-29 15:00:51 +08003614 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3615 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3616 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3617 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3618 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3619 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3620 maxDimension = caps.maxCubeMapTextureSize;
3621 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003622
He Yunchaoced53ae2016-11-29 15:00:51 +08003623 case GL_TEXTURE_2D_ARRAY:
3624 maxDimension = caps.max2DTextureSize;
3625 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003626
He Yunchaoced53ae2016-11-29 15:00:51 +08003627 case GL_TEXTURE_3D:
3628 maxDimension = caps.max3DTextureSize;
3629 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003630
He Yunchaoced53ae2016-11-29 15:00:51 +08003631 default:
3632 context->handleError(Error(GL_INVALID_ENUM));
3633 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003634 }
3635
Jamie Madillc29968b2016-01-20 11:17:23 -05003636 gl::Texture *texture =
3637 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003638 if (!texture)
3639 {
Jamie Madill437fa652016-05-03 15:13:24 -04003640 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003641 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003642 }
3643
Geoff Lang69cce582015-09-17 13:20:36 -04003644 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003645 {
Jamie Madill437fa652016-05-03 15:13:24 -04003646 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003647 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003648 }
3649
Geoff Langca271392017-04-05 12:30:00 -04003650 const gl::InternalFormat &formatInfo =
3651 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04003652
Geoff Lang966c9402017-04-18 12:38:27 -04003653 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04003654 {
Jamie Madill437fa652016-05-03 15:13:24 -04003655 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003656 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003657 }
3658
3659 if (isSubImage)
3660 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003661 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3662 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3663 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003664 {
Jamie Madill437fa652016-05-03 15:13:24 -04003665 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003666 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003667 }
3668 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003669 else
3670 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003671 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003672 {
Jamie Madill437fa652016-05-03 15:13:24 -04003673 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003674 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003675 }
3676
Geoff Langeb66a6e2016-10-31 13:06:12 -04003677 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003678 {
Jamie Madill437fa652016-05-03 15:13:24 -04003679 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003680 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003681 }
3682
3683 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003684 if (static_cast<int>(width) > maxLevelDimension ||
3685 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003686 {
Jamie Madill437fa652016-05-03 15:13:24 -04003687 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003688 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003689 }
3690 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003691
Jamie Madill0c8abca2016-07-22 20:21:26 -04003692 if (textureFormatOut)
3693 {
3694 *textureFormatOut = texture->getFormat(target, level);
3695 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003696
3697 // Detect texture copying feedback loops for WebGL.
3698 if (context->getExtensions().webglCompatibility)
3699 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05003700 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05003701 {
3702 context->handleError(Error(GL_INVALID_OPERATION,
3703 "Texture copying feedback loop formed between Framebuffer "
3704 "and specified Texture level."));
3705 return false;
3706 }
3707 }
3708
Jamie Madill560a8d82014-05-21 13:06:20 -04003709 return true;
3710}
3711
Jiajia Qind9671222016-11-29 16:30:31 +08003712bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003713{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003714 switch (mode)
3715 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003716 case GL_POINTS:
3717 case GL_LINES:
3718 case GL_LINE_LOOP:
3719 case GL_LINE_STRIP:
3720 case GL_TRIANGLES:
3721 case GL_TRIANGLE_STRIP:
3722 case GL_TRIANGLE_FAN:
3723 break;
3724 default:
3725 context->handleError(Error(GL_INVALID_ENUM));
3726 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003727 }
3728
Jamie Madill250d33f2014-06-06 17:09:03 -04003729 if (count < 0)
3730 {
Jamie Madill437fa652016-05-03 15:13:24 -04003731 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003732 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003733 }
3734
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003735 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003736
Jamie Madill250d33f2014-06-06 17:09:03 -04003737 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003738 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003739 {
Jamie Madill437fa652016-05-03 15:13:24 -04003740 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003741 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003742 }
3743
Jamie Madillcbcde722017-01-06 14:50:00 -05003744 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3745 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003746 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003747 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3748 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003749 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003750 const FramebufferAttachment *dsAttachment =
3751 framebuffer->getStencilOrDepthStencilAttachment();
3752 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003753 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003754 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003755
3756 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3757 bool differentWritemasks =
3758 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3759 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3760 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3761 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3762
3763 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003764 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003765 if (!context->getExtensions().webglCompatibility)
3766 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003767 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3768 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003769 }
Jamie Madill437fa652016-05-03 15:13:24 -04003770 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003771 return false;
3772 }
Jamie Madillac528012014-06-20 13:21:23 -04003773 }
3774
Jamie Madilldd43e6c2017-03-24 14:18:49 -04003775 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003776 {
Jamie Madill437fa652016-05-03 15:13:24 -04003777 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003778 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003779 }
3780
Geoff Lang7dd2e102014-11-10 15:19:26 -05003781 gl::Program *program = state.getProgram();
3782 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003783 {
Jamie Madill437fa652016-05-03 15:13:24 -04003784 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003785 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003786 }
3787
Yunchao Hef81ce4a2017-04-24 10:49:17 +08003788 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003789 {
Jamie Madill437fa652016-05-03 15:13:24 -04003790 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003791 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003792 }
3793
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003794 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003795 for (unsigned int uniformBlockIndex = 0;
3796 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003797 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003798 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003799 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003800 const OffsetBindingPointer<Buffer> &uniformBuffer =
3801 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003802
Geoff Lang5d124a62015-09-15 13:03:27 -04003803 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003804 {
3805 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003806 context->handleError(
3807 Error(GL_INVALID_OPERATION,
3808 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003809 return false;
3810 }
3811
Geoff Lang5d124a62015-09-15 13:03:27 -04003812 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003813 if (uniformBufferSize == 0)
3814 {
3815 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003816 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003817 }
3818
Jamie Madill62d31cb2015-09-11 13:25:51 -04003819 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003820 {
3821 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003822 context->handleError(
3823 Error(GL_INVALID_OPERATION,
3824 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003825 return false;
3826 }
3827 }
3828
Jamie Madilla4595b82017-01-11 17:36:34 -05003829 // Detect rendering feedback loops for WebGL.
3830 if (context->getExtensions().webglCompatibility)
3831 {
3832 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3833 {
3834 context->handleError(
3835 Error(GL_INVALID_OPERATION,
3836 "Rendering feedback loop formed between Framebuffer and active Texture."));
3837 return false;
3838 }
3839 }
3840
Jamie Madill250d33f2014-06-06 17:09:03 -04003841 // No-op if zero count
3842 return (count > 0);
3843}
3844
Jamie Madillc1d770e2017-04-13 17:31:24 -04003845bool ValidateDrawArraysCommon(ValidationContext *context,
3846 GLenum mode,
3847 GLint first,
3848 GLsizei count,
3849 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003850{
Jamie Madillfd716582014-06-06 17:09:04 -04003851 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003852 {
Jamie Madill437fa652016-05-03 15:13:24 -04003853 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003854 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003855 }
3856
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003857 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003858 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003859 if (curTransformFeedback && curTransformFeedback->isActive() &&
3860 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003861 {
3862 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003863 // that does not match the current transform feedback object's draw mode (if transform
3864 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003865 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003866 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003867 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003868 }
3869
Jiajia Qind9671222016-11-29 16:30:31 +08003870 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003871 {
3872 return false;
3873 }
3874
Corentin Wallez71168a02016-12-19 15:11:18 -08003875 // Check the computation of maxVertex doesn't overflow.
3876 // - first < 0 or count < 0 have been checked as an error condition
3877 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3878 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3879 ASSERT(count > 0 && first >= 0);
3880 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3881 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003882 {
3883 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3884 return false;
3885 }
3886
Corentin Wallez71168a02016-12-19 15:11:18 -08003887 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003888 {
3889 return false;
3890 }
3891
3892 return true;
3893}
3894
He Yunchaoced53ae2016-11-29 15:00:51 +08003895bool ValidateDrawArraysInstanced(Context *context,
3896 GLenum mode,
3897 GLint first,
3898 GLsizei count,
3899 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003900{
Geoff Lang407d4e72017-04-12 14:54:11 -04003901 if (context->getExtensions().webglCompatibility && !ValidateDrawInstancedANGLEAndWebGL(context))
Jamie Madillfd716582014-06-06 17:09:04 -04003902 {
3903 return false;
3904 }
3905
Geoff Lang407d4e72017-04-12 14:54:11 -04003906 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04003907}
3908
He Yunchaoced53ae2016-11-29 15:00:51 +08003909bool ValidateDrawArraysInstancedANGLE(Context *context,
3910 GLenum mode,
3911 GLint first,
3912 GLsizei count,
3913 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003914{
Geoff Lang407d4e72017-04-12 14:54:11 -04003915 if (!ValidateDrawInstancedANGLEAndWebGL(context))
Geoff Lang87a93302014-09-16 13:29:43 -04003916 {
3917 return false;
3918 }
3919
Geoff Lang407d4e72017-04-12 14:54:11 -04003920 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04003921}
3922
Jiajia Qind9671222016-11-29 16:30:31 +08003923bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003924{
Jamie Madill250d33f2014-06-06 17:09:03 -04003925 switch (type)
3926 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003927 case GL_UNSIGNED_BYTE:
3928 case GL_UNSIGNED_SHORT:
3929 break;
3930 case GL_UNSIGNED_INT:
3931 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3932 {
3933 context->handleError(Error(GL_INVALID_ENUM));
3934 return false;
3935 }
3936 break;
3937 default:
3938 context->handleError(Error(GL_INVALID_ENUM));
3939 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003940 }
3941
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003942 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003943
3944 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003945 if (curTransformFeedback && curTransformFeedback->isActive() &&
3946 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003947 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003948 // It is an invalid operation to call DrawElements, DrawRangeElements or
3949 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003950 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003951 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003952 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003953 }
3954
Jiajia Qind9671222016-11-29 16:30:31 +08003955 return true;
3956}
3957
3958bool ValidateDrawElements(ValidationContext *context,
3959 GLenum mode,
3960 GLsizei count,
3961 GLenum type,
3962 const GLvoid *indices,
3963 GLsizei primcount,
3964 IndexRange *indexRangeOut)
3965{
3966 if (!ValidateDrawElementsBase(context, type))
3967 return false;
3968
3969 const State &state = context->getGLState();
3970
Jamie Madill250d33f2014-06-06 17:09:03 -04003971 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003972 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003973 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003974 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04003975 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003976 }
3977
He Yunchaoced53ae2016-11-29 15:00:51 +08003978 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003979 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003980
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003981 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3982
3983 if (context->getExtensions().webglCompatibility)
3984 {
3985 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3986 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3987 {
3988 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3989 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3990 // data type passed to the call, or an INVALID_OPERATION error is generated.
3991 context->handleError(Error(GL_INVALID_OPERATION,
3992 "indices must be a multiple of the element type size."));
3993 return false;
3994 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003995
3996 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3997 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3998 // error is generated.
3999 if (reinterpret_cast<intptr_t>(indices) < 0)
4000 {
4001 context->handleError(Error(GL_INVALID_VALUE, "Offset < 0."));
4002 return false;
4003 }
Geoff Langfeb8c682017-02-13 16:07:35 -05004004 }
4005
4006 if (context->getExtensions().webglCompatibility ||
4007 !context->getGLState().areClientArraysEnabled())
4008 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05004009 if (!elementArrayBuffer && count > 0)
4010 {
4011 // [WebGL 1.0] Section 6.2 No Client Side Arrays
4012 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
4013 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
4014 context->handleError(Error(GL_INVALID_OPERATION,
4015 "There is no element array buffer bound and count > 0."));
4016 return false;
4017 }
4018 }
4019
Corentin Wallez0844f2d2017-01-31 17:02:59 -05004020 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04004021 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05004022 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04004023 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05004024 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
4025 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
4026 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
4027 constexpr uint64_t kMaxTypeSize = 8;
4028 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
4029 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
4030 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05004031
Corentin Wallezfe9306a2017-02-01 17:41:05 -05004032 uint64_t typeSize = typeBytes;
4033 uint64_t elementCount = static_cast<uint64_t>(count);
4034 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
4035
4036 // Doing the multiplication here is overflow-safe
4037 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
4038
4039 // The offset can be any value, check for overflows
4040 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
4041 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05004042 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05004043 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
Corentin Wallez0844f2d2017-01-31 17:02:59 -05004044 return false;
4045 }
4046
Corentin Wallezfe9306a2017-02-01 17:41:05 -05004047 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
4048 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05004049 {
4050 context->handleError(
4051 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
4052 return false;
4053 }
4054 }
4055 else if (!indices)
4056 {
4057 // This is an application error that would normally result in a crash,
4058 // but we catch it and return an error
4059 context->handleError(
4060 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04004061 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04004062 }
Jamie Madillae3000b2014-08-25 15:47:51 -04004063 }
4064
Jiajia Qind9671222016-11-29 16:30:31 +08004065 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07004066 {
4067 return false;
4068 }
4069
Jamie Madill2b976812014-08-25 15:47:49 -04004070 // Use max index to validate if our vertex buffers are large enough for the pull.
4071 // TODO: offer fast path, with disabled index validation.
4072 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
4073 if (elementArrayBuffer)
4074 {
Jacek Cabana5521de2014-10-01 17:23:46 +02004075 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04004076 Error error =
4077 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
4078 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04004079 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04004080 {
Jamie Madill437fa652016-05-03 15:13:24 -04004081 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04004082 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04004083 }
4084 }
4085 else
4086 {
Geoff Lang3edfe032015-09-04 16:38:24 -04004087 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04004088 }
4089
Jamie Madille79b1e12015-11-04 16:36:37 -05004090 // If we use an index greater than our maximum supported index range, return an error.
4091 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
4092 // return an error if possible here.
4093 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
4094 {
Jamie Madill437fa652016-05-03 15:13:24 -04004095 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05004096 return false;
4097 }
4098
Corentin Wallez92db6942016-12-09 13:10:36 -05004099 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
4100 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04004101 {
4102 return false;
4103 }
4104
Geoff Lang3edfe032015-09-04 16:38:24 -04004105 // No op if there are no real indices in the index data (all are primitive restart).
4106 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04004107}
4108
Geoff Langb1196682014-07-23 13:47:29 -04004109bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04004110 GLenum mode,
4111 GLsizei count,
4112 GLenum type,
4113 const GLvoid *indices,
4114 GLsizei primcount,
4115 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04004116{
Geoff Lang407d4e72017-04-12 14:54:11 -04004117 if (context->getExtensions().webglCompatibility && !ValidateDrawInstancedANGLEAndWebGL(context))
Jamie Madillfd716582014-06-06 17:09:04 -04004118 {
4119 return false;
4120 }
4121
Geoff Lang407d4e72017-04-12 14:54:11 -04004122 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount,
4123 indexRangeOut);
Jamie Madill250d33f2014-06-06 17:09:03 -04004124}
4125
Geoff Lang3edfe032015-09-04 16:38:24 -04004126bool ValidateDrawElementsInstancedANGLE(Context *context,
4127 GLenum mode,
4128 GLsizei count,
4129 GLenum type,
4130 const GLvoid *indices,
4131 GLsizei primcount,
4132 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04004133{
Geoff Lang407d4e72017-04-12 14:54:11 -04004134 if (!ValidateDrawInstancedANGLEAndWebGL(context))
Geoff Lang87a93302014-09-16 13:29:43 -04004135 {
4136 return false;
4137 }
4138
Geoff Lang407d4e72017-04-12 14:54:11 -04004139 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount,
4140 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04004141}
4142
He Yunchaoced53ae2016-11-29 15:00:51 +08004143bool ValidateFramebufferTextureBase(Context *context,
4144 GLenum target,
4145 GLenum attachment,
4146 GLuint texture,
4147 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04004148{
Jamie Madill55ec3b12014-07-03 10:38:57 -04004149 if (!ValidFramebufferTarget(target))
4150 {
Jamie Madill437fa652016-05-03 15:13:24 -04004151 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04004152 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004153 }
4154
4155 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04004156 {
4157 return false;
4158 }
4159
Jamie Madill55ec3b12014-07-03 10:38:57 -04004160 if (texture != 0)
4161 {
4162 gl::Texture *tex = context->getTexture(texture);
4163
Yunchao He4f285442017-04-21 12:15:49 +08004164 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04004165 {
Jamie Madill437fa652016-05-03 15:13:24 -04004166 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04004167 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004168 }
4169
4170 if (level < 0)
4171 {
Jamie Madill437fa652016-05-03 15:13:24 -04004172 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04004173 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004174 }
4175 }
4176
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004177 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04004178 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04004179
Jamie Madill84115c92015-04-23 15:00:07 -04004180 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04004181 {
Jamie Madill437fa652016-05-03 15:13:24 -04004182 context->handleError(
4183 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04004184 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004185 }
4186
4187 return true;
4188}
4189
He Yunchaoced53ae2016-11-29 15:00:51 +08004190bool ValidateFramebufferTexture2D(Context *context,
4191 GLenum target,
4192 GLenum attachment,
4193 GLenum textarget,
4194 GLuint texture,
4195 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04004196{
He Yunchaoced53ae2016-11-29 15:00:51 +08004197 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
4198 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03004199 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
4200 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04004201 {
Jamie Madill437fa652016-05-03 15:13:24 -04004202 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04004203 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004204 }
4205
4206 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04004207 {
4208 return false;
4209 }
4210
Jamie Madill55ec3b12014-07-03 10:38:57 -04004211 if (texture != 0)
4212 {
4213 gl::Texture *tex = context->getTexture(texture);
4214 ASSERT(tex);
4215
Jamie Madill2a6564e2014-07-11 09:53:19 -04004216 const gl::Caps &caps = context->getCaps();
4217
Jamie Madill55ec3b12014-07-03 10:38:57 -04004218 switch (textarget)
4219 {
He Yunchaoced53ae2016-11-29 15:00:51 +08004220 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04004221 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04004222 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04004223 {
Jamie Madill437fa652016-05-03 15:13:24 -04004224 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04004225 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004226 }
4227 if (tex->getTarget() != GL_TEXTURE_2D)
4228 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08004229 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 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4237 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4238 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4239 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4240 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4241 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04004242 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04004243 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04004244 {
Jamie Madill437fa652016-05-03 15:13:24 -04004245 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04004246 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004247 }
4248 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
4249 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08004250 context->handleError(Error(GL_INVALID_OPERATION,
4251 "Textarget must match the texture target type."));
4252 return false;
4253 }
4254 }
4255 break;
4256
4257 case GL_TEXTURE_2D_MULTISAMPLE:
4258 {
4259 if (context->getClientVersion() < ES_3_1)
4260 {
4261 context->handleError(Error(GL_INVALID_OPERATION,
4262 "Texture target requires at least OpenGL ES 3.1."));
4263 return false;
4264 }
4265
4266 if (level != 0)
4267 {
4268 context->handleError(
4269 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
4270 return false;
4271 }
4272 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
4273 {
4274 context->handleError(Error(GL_INVALID_OPERATION,
4275 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04004276 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004277 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04004278 }
4279 break;
4280
He Yunchaoced53ae2016-11-29 15:00:51 +08004281 default:
4282 context->handleError(Error(GL_INVALID_ENUM));
4283 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04004284 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05004285
Jamie Madilla3944d42016-07-22 22:13:26 -04004286 const Format &format = tex->getFormat(textarget, level);
4287 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05004288 {
Jamie Madill437fa652016-05-03 15:13:24 -04004289 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05004290 return false;
4291 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04004292 }
4293
Jamie Madill570f7c82014-07-03 10:38:54 -04004294 return true;
4295}
4296
Geoff Langb1196682014-07-23 13:47:29 -04004297bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04004298{
4299 if (program == 0)
4300 {
Jamie Madill437fa652016-05-03 15:13:24 -04004301 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04004302 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04004303 }
4304
Dian Xiang769769a2015-09-09 15:20:08 -07004305 gl::Program *programObject = GetValidProgram(context, program);
4306 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05004307 {
4308 return false;
4309 }
4310
Jamie Madill0063c512014-08-25 15:47:53 -04004311 if (!programObject || !programObject->isLinked())
4312 {
Jamie Madill437fa652016-05-03 15:13:24 -04004313 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04004314 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04004315 }
4316
Geoff Lang7dd2e102014-11-10 15:19:26 -05004317 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04004318 {
Jamie Madill437fa652016-05-03 15:13:24 -04004319 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04004320 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04004321 }
4322
Jamie Madill0063c512014-08-25 15:47:53 -04004323 return true;
4324}
4325
He Yunchaoced53ae2016-11-29 15:00:51 +08004326bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04004327{
4328 return ValidateGetUniformBase(context, program, location);
4329}
4330
He Yunchaoced53ae2016-11-29 15:00:51 +08004331bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04004332{
Jamie Madill78f41802014-08-25 15:47:55 -04004333 return ValidateGetUniformBase(context, program, location);
4334}
4335
Geoff Langf41d0ee2016-10-07 13:04:23 -04004336static bool ValidateSizedGetUniform(Context *context,
4337 GLuint program,
4338 GLint location,
4339 GLsizei bufSize,
4340 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04004341{
Geoff Langf41d0ee2016-10-07 13:04:23 -04004342 if (length)
4343 {
4344 *length = 0;
4345 }
4346
Jamie Madill78f41802014-08-25 15:47:55 -04004347 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04004348 {
Jamie Madill78f41802014-08-25 15:47:55 -04004349 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04004350 }
4351
Geoff Langf41d0ee2016-10-07 13:04:23 -04004352 if (bufSize < 0)
4353 {
4354 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4355 return false;
4356 }
4357
Jamie Madilla502c742014-08-28 17:19:13 -04004358 gl::Program *programObject = context->getProgram(program);
4359 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04004360
Jamie Madill78f41802014-08-25 15:47:55 -04004361 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04004362 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08004363 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04004364 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04004365 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04004366 context->handleError(
4367 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04004368 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04004369 }
4370
Geoff Langf41d0ee2016-10-07 13:04:23 -04004371 if (length)
4372 {
Geoff Lang94177fb2016-11-14 16:12:26 -05004373 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04004374 }
4375
Jamie Madill0063c512014-08-25 15:47:53 -04004376 return true;
4377}
4378
He Yunchaoced53ae2016-11-29 15:00:51 +08004379bool ValidateGetnUniformfvEXT(Context *context,
4380 GLuint program,
4381 GLint location,
4382 GLsizei bufSize,
4383 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04004384{
Geoff Langf41d0ee2016-10-07 13:04:23 -04004385 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04004386}
4387
He Yunchaoced53ae2016-11-29 15:00:51 +08004388bool ValidateGetnUniformivEXT(Context *context,
4389 GLuint program,
4390 GLint location,
4391 GLsizei bufSize,
4392 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04004393{
Geoff Langf41d0ee2016-10-07 13:04:23 -04004394 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
4395}
4396
4397bool ValidateGetUniformfvRobustANGLE(Context *context,
4398 GLuint program,
4399 GLint location,
4400 GLsizei bufSize,
4401 GLsizei *length,
4402 GLfloat *params)
4403{
4404 if (!ValidateRobustEntryPoint(context, bufSize))
4405 {
4406 return false;
4407 }
4408
4409 // bufSize is validated in ValidateSizedGetUniform
4410 return ValidateSizedGetUniform(context, program, location, bufSize, length);
4411}
4412
4413bool ValidateGetUniformivRobustANGLE(Context *context,
4414 GLuint program,
4415 GLint location,
4416 GLsizei bufSize,
4417 GLsizei *length,
4418 GLint *params)
4419{
4420 if (!ValidateRobustEntryPoint(context, bufSize))
4421 {
4422 return false;
4423 }
4424
4425 // bufSize is validated in ValidateSizedGetUniform
4426 return ValidateSizedGetUniform(context, program, location, bufSize, length);
4427}
4428
4429bool ValidateGetUniformuivRobustANGLE(Context *context,
4430 GLuint program,
4431 GLint location,
4432 GLsizei bufSize,
4433 GLsizei *length,
4434 GLuint *params)
4435{
4436 if (!ValidateRobustEntryPoint(context, bufSize))
4437 {
4438 return false;
4439 }
4440
4441 if (context->getClientMajorVersion() < 3)
4442 {
4443 context->handleError(
4444 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
4445 return false;
4446 }
4447
4448 // bufSize is validated in ValidateSizedGetUniform
4449 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04004450}
4451
He Yunchaoced53ae2016-11-29 15:00:51 +08004452bool ValidateDiscardFramebufferBase(Context *context,
4453 GLenum target,
4454 GLsizei numAttachments,
4455 const GLenum *attachments,
4456 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07004457{
4458 if (numAttachments < 0)
4459 {
Jamie Madill437fa652016-05-03 15:13:24 -04004460 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07004461 return false;
4462 }
4463
4464 for (GLsizei i = 0; i < numAttachments; ++i)
4465 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02004466 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07004467 {
4468 if (defaultFramebuffer)
4469 {
Jamie Madill437fa652016-05-03 15:13:24 -04004470 context->handleError(Error(
4471 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07004472 return false;
4473 }
4474
4475 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
4476 {
Jamie Madill437fa652016-05-03 15:13:24 -04004477 context->handleError(Error(GL_INVALID_OPERATION,
4478 "Requested color attachment is greater than the maximum "
4479 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07004480 return false;
4481 }
4482 }
4483 else
4484 {
4485 switch (attachments[i])
4486 {
He Yunchaoced53ae2016-11-29 15:00:51 +08004487 case GL_DEPTH_ATTACHMENT:
4488 case GL_STENCIL_ATTACHMENT:
4489 case GL_DEPTH_STENCIL_ATTACHMENT:
4490 if (defaultFramebuffer)
4491 {
4492 context->handleError(
4493 Error(GL_INVALID_ENUM,
4494 "Invalid attachment when the default framebuffer is bound"));
4495 return false;
4496 }
4497 break;
4498 case GL_COLOR:
4499 case GL_DEPTH:
4500 case GL_STENCIL:
4501 if (!defaultFramebuffer)
4502 {
4503 context->handleError(
4504 Error(GL_INVALID_ENUM,
4505 "Invalid attachment when the default framebuffer is not bound"));
4506 return false;
4507 }
4508 break;
4509 default:
4510 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07004511 return false;
Austin Kinross08332632015-05-05 13:35:47 -07004512 }
4513 }
4514 }
4515
4516 return true;
4517}
4518
Austin Kinross6ee1e782015-05-29 17:05:37 -07004519bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
4520{
4521 // Note that debug marker calls must not set error state
4522
4523 if (length < 0)
4524 {
4525 return false;
4526 }
4527
4528 if (marker == nullptr)
4529 {
4530 return false;
4531 }
4532
4533 return true;
4534}
4535
4536bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
4537{
4538 // Note that debug marker calls must not set error state
4539
4540 if (length < 0)
4541 {
4542 return false;
4543 }
4544
4545 if (length > 0 && marker == nullptr)
4546 {
4547 return false;
4548 }
4549
4550 return true;
4551}
4552
Geoff Langdcab33b2015-07-21 13:03:16 -04004553bool ValidateEGLImageTargetTexture2DOES(Context *context,
4554 egl::Display *display,
4555 GLenum target,
4556 egl::Image *image)
4557{
Geoff Langa8406172015-07-21 16:53:39 -04004558 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4559 {
Jamie Madill437fa652016-05-03 15:13:24 -04004560 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004561 return false;
4562 }
4563
4564 switch (target)
4565 {
4566 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004567 if (!context->getExtensions().eglImage)
4568 {
4569 context->handleError(Error(
4570 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4571 }
4572 break;
4573
4574 case GL_TEXTURE_EXTERNAL_OES:
4575 if (!context->getExtensions().eglImageExternal)
4576 {
4577 context->handleError(Error(
4578 GL_INVALID_ENUM,
4579 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4580 }
Geoff Langa8406172015-07-21 16:53:39 -04004581 break;
4582
4583 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004584 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004585 return false;
4586 }
4587
4588 if (!display->isValidImage(image))
4589 {
Jamie Madill437fa652016-05-03 15:13:24 -04004590 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004591 return false;
4592 }
4593
4594 if (image->getSamples() > 0)
4595 {
Jamie Madill437fa652016-05-03 15:13:24 -04004596 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004597 "cannot create a 2D texture from a multisampled EGL image."));
4598 return false;
4599 }
4600
Geoff Langca271392017-04-05 12:30:00 -04004601 const TextureCaps &textureCaps =
4602 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04004603 if (!textureCaps.texturable)
4604 {
Jamie Madill437fa652016-05-03 15:13:24 -04004605 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004606 "EGL image internal format is not supported as a texture."));
4607 return false;
4608 }
4609
Geoff Langdcab33b2015-07-21 13:03:16 -04004610 return true;
4611}
4612
4613bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4614 egl::Display *display,
4615 GLenum target,
4616 egl::Image *image)
4617{
Geoff Langa8406172015-07-21 16:53:39 -04004618 if (!context->getExtensions().eglImage)
4619 {
Jamie Madill437fa652016-05-03 15:13:24 -04004620 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004621 return false;
4622 }
4623
4624 switch (target)
4625 {
4626 case GL_RENDERBUFFER:
4627 break;
4628
4629 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004630 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004631 return false;
4632 }
4633
4634 if (!display->isValidImage(image))
4635 {
Jamie Madill437fa652016-05-03 15:13:24 -04004636 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004637 return false;
4638 }
4639
Geoff Langca271392017-04-05 12:30:00 -04004640 const TextureCaps &textureCaps =
4641 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04004642 if (!textureCaps.renderable)
4643 {
Jamie Madill437fa652016-05-03 15:13:24 -04004644 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004645 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4646 return false;
4647 }
4648
Geoff Langdcab33b2015-07-21 13:03:16 -04004649 return true;
4650}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004651
4652bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4653{
Geoff Lang36167ab2015-12-07 10:27:14 -05004654 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004655 {
4656 // The default VAO should always exist
4657 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004658 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004659 return false;
4660 }
4661
4662 return true;
4663}
4664
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004665bool ValidateLinkProgram(Context *context, GLuint program)
4666{
4667 if (context->hasActiveTransformFeedback(program))
4668 {
4669 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004670 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004671 "Cannot link program while program is associated with an active "
4672 "transform feedback object."));
4673 return false;
4674 }
Jamie Madillc1d770e2017-04-13 17:31:24 -04004675
4676 Program *programObject = GetValidProgram(context, program);
4677 if (!programObject)
4678 {
4679 return false;
4680 }
4681
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004682 return true;
4683}
4684
Geoff Langc5629752015-12-07 16:29:04 -05004685bool ValidateProgramBinaryBase(Context *context,
4686 GLuint program,
4687 GLenum binaryFormat,
4688 const void *binary,
4689 GLint length)
4690{
4691 Program *programObject = GetValidProgram(context, program);
4692 if (programObject == nullptr)
4693 {
4694 return false;
4695 }
4696
4697 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4698 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4699 programBinaryFormats.end())
4700 {
Jamie Madill437fa652016-05-03 15:13:24 -04004701 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004702 return false;
4703 }
4704
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004705 if (context->hasActiveTransformFeedback(program))
4706 {
4707 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004708 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004709 "Cannot change program binary while program is associated with "
4710 "an active transform feedback object."));
4711 return false;
4712 }
4713
Geoff Langc5629752015-12-07 16:29:04 -05004714 return true;
4715}
4716
4717bool ValidateGetProgramBinaryBase(Context *context,
4718 GLuint program,
4719 GLsizei bufSize,
4720 GLsizei *length,
4721 GLenum *binaryFormat,
4722 void *binary)
4723{
4724 Program *programObject = GetValidProgram(context, program);
4725 if (programObject == nullptr)
4726 {
4727 return false;
4728 }
4729
4730 if (!programObject->isLinked())
4731 {
Jamie Madill437fa652016-05-03 15:13:24 -04004732 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004733 return false;
4734 }
4735
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004736 if (context->getCaps().programBinaryFormats.empty())
4737 {
4738 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4739 return false;
4740 }
4741
Geoff Langc5629752015-12-07 16:29:04 -05004742 return true;
4743}
Jamie Madillc29968b2016-01-20 11:17:23 -05004744
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004745bool ValidateUseProgram(Context *context, GLuint program)
4746{
4747 if (program != 0)
4748 {
4749 Program *programObject = context->getProgram(program);
4750 if (!programObject)
4751 {
4752 // ES 3.1.0 section 7.3 page 72
4753 if (context->getShader(program))
4754 {
Jamie Madill437fa652016-05-03 15:13:24 -04004755 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004756 Error(GL_INVALID_OPERATION,
4757 "Attempted to use a single shader instead of a shader program."));
4758 return false;
4759 }
4760 else
4761 {
Jamie Madill437fa652016-05-03 15:13:24 -04004762 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004763 return false;
4764 }
4765 }
4766 if (!programObject->isLinked())
4767 {
Jamie Madill437fa652016-05-03 15:13:24 -04004768 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004769 return false;
4770 }
4771 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004772 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004773 {
4774 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004775 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004776 Error(GL_INVALID_OPERATION,
4777 "Cannot change active program while transform feedback is unpaused."));
4778 return false;
4779 }
4780
4781 return true;
4782}
4783
Jamie Madillc29968b2016-01-20 11:17:23 -05004784bool ValidateCopyTexImage2D(ValidationContext *context,
4785 GLenum target,
4786 GLint level,
4787 GLenum internalformat,
4788 GLint x,
4789 GLint y,
4790 GLsizei width,
4791 GLsizei height,
4792 GLint border)
4793{
Martin Radev1be913c2016-07-11 17:59:16 +03004794 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004795 {
4796 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4797 0, x, y, width, height, border);
4798 }
4799
Martin Radev1be913c2016-07-11 17:59:16 +03004800 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004801 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4802 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004803}
Jamie Madillc29968b2016-01-20 11:17:23 -05004804
4805bool ValidateFramebufferRenderbuffer(Context *context,
4806 GLenum target,
4807 GLenum attachment,
4808 GLenum renderbuffertarget,
4809 GLuint renderbuffer)
4810{
4811 if (!ValidFramebufferTarget(target) ||
4812 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4813 {
Jamie Madill437fa652016-05-03 15:13:24 -04004814 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004815 return false;
4816 }
4817
4818 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4819 renderbuffertarget, renderbuffer);
4820}
4821
4822bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4823{
4824 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4825 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4826 {
Jamie Madill437fa652016-05-03 15:13:24 -04004827 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004828 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4829 return false;
4830 }
4831
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004832 ASSERT(context->getGLState().getDrawFramebuffer());
4833 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004834 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4835
4836 // This should come first before the check for the default frame buffer
4837 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4838 // rather than INVALID_OPERATION
4839 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4840 {
4841 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4842
4843 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004844 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4845 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004846 {
4847 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004848 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4849 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4850 // 3.1 is still a bit ambiguous about the error, but future specs are
4851 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004852 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004853 return false;
4854 }
4855 else if (bufs[colorAttachment] >= maxColorAttachment)
4856 {
Jamie Madill437fa652016-05-03 15:13:24 -04004857 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004858 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004859 return false;
4860 }
4861 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4862 frameBufferId != 0)
4863 {
4864 // INVALID_OPERATION-GL is bound to buffer and ith argument
4865 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004866 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004867 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4868 return false;
4869 }
4870 }
4871
4872 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4873 // and n is not 1 or bufs is bound to value other than BACK and NONE
4874 if (frameBufferId == 0)
4875 {
4876 if (n != 1)
4877 {
Jamie Madill437fa652016-05-03 15:13:24 -04004878 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004879 "n must be 1 when GL is bound to the default framebuffer"));
4880 return false;
4881 }
4882
4883 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4884 {
Jamie Madill437fa652016-05-03 15:13:24 -04004885 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004886 GL_INVALID_OPERATION,
4887 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4888 return false;
4889 }
4890 }
4891
4892 return true;
4893}
4894
4895bool ValidateCopyTexSubImage2D(Context *context,
4896 GLenum target,
4897 GLint level,
4898 GLint xoffset,
4899 GLint yoffset,
4900 GLint x,
4901 GLint y,
4902 GLsizei width,
4903 GLsizei height)
4904{
Martin Radev1be913c2016-07-11 17:59:16 +03004905 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004906 {
4907 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4908 yoffset, x, y, width, height, 0);
4909 }
4910
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004911 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4912 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004913}
4914
Geoff Lang496c02d2016-10-20 11:38:11 -07004915bool ValidateGetBufferPointervBase(Context *context,
4916 GLenum target,
4917 GLenum pname,
4918 GLsizei *length,
4919 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004920{
Geoff Lang496c02d2016-10-20 11:38:11 -07004921 if (length)
4922 {
4923 *length = 0;
4924 }
4925
4926 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4927 {
4928 context->handleError(
4929 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004930 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004931 return false;
4932 }
4933
Olli Etuaho4f667482016-03-30 15:56:35 +03004934 if (!ValidBufferTarget(context, target))
4935 {
Jamie Madill437fa652016-05-03 15:13:24 -04004936 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004937 return false;
4938 }
4939
Geoff Lang496c02d2016-10-20 11:38:11 -07004940 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004941 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004942 case GL_BUFFER_MAP_POINTER:
4943 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004944
Geoff Lang496c02d2016-10-20 11:38:11 -07004945 default:
4946 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4947 return false;
4948 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004949
4950 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4951 // target bound to zero generate an INVALID_OPERATION error."
4952 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004953 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004954 {
Jamie Madill437fa652016-05-03 15:13:24 -04004955 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004956 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4957 return false;
4958 }
4959
Geoff Lang496c02d2016-10-20 11:38:11 -07004960 if (length)
4961 {
4962 *length = 1;
4963 }
4964
Olli Etuaho4f667482016-03-30 15:56:35 +03004965 return true;
4966}
4967
4968bool ValidateUnmapBufferBase(Context *context, GLenum target)
4969{
4970 if (!ValidBufferTarget(context, target))
4971 {
Jamie Madill437fa652016-05-03 15:13:24 -04004972 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004973 return false;
4974 }
4975
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004976 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004977
4978 if (buffer == nullptr || !buffer->isMapped())
4979 {
Jamie Madill437fa652016-05-03 15:13:24 -04004980 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004981 return false;
4982 }
4983
4984 return true;
4985}
4986
4987bool ValidateMapBufferRangeBase(Context *context,
4988 GLenum target,
4989 GLintptr offset,
4990 GLsizeiptr length,
4991 GLbitfield access)
4992{
4993 if (!ValidBufferTarget(context, target))
4994 {
Jamie Madill437fa652016-05-03 15:13:24 -04004995 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004996 return false;
4997 }
4998
4999 if (offset < 0 || length < 0)
5000 {
Jamie Madill437fa652016-05-03 15:13:24 -04005001 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03005002 return false;
5003 }
5004
Jamie Madilldfde6ab2016-06-09 07:07:18 -07005005 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03005006
5007 if (!buffer)
5008 {
Jamie Madill437fa652016-05-03 15:13:24 -04005009 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03005010 return false;
5011 }
5012
5013 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04005014 CheckedNumeric<size_t> checkedOffset(offset);
5015 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03005016
Jamie Madille2e406c2016-06-02 13:04:10 -04005017 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03005018 {
Jamie Madill437fa652016-05-03 15:13:24 -04005019 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03005020 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
5021 return false;
5022 }
5023
5024 // Check for invalid bits in the mask
5025 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
5026 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
5027 GL_MAP_UNSYNCHRONIZED_BIT;
5028
5029 if (access & ~(allAccessBits))
5030 {
Jamie Madill437fa652016-05-03 15:13:24 -04005031 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03005032 return false;
5033 }
5034
5035 if (length == 0)
5036 {
Jamie Madill437fa652016-05-03 15:13:24 -04005037 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03005038 return false;
5039 }
5040
5041 if (buffer->isMapped())
5042 {
Jamie Madill437fa652016-05-03 15:13:24 -04005043 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03005044 return false;
5045 }
5046
5047 // Check for invalid bit combinations
5048 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
5049 {
Jamie Madill437fa652016-05-03 15:13:24 -04005050 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03005051 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
5052 return false;
5053 }
5054
5055 GLbitfield writeOnlyBits =
5056 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
5057
5058 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
5059 {
Jamie Madill437fa652016-05-03 15:13:24 -04005060 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03005061 "Invalid access bits when mapping buffer for reading: 0x%X.",
5062 access));
5063 return false;
5064 }
5065
5066 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
5067 {
Jamie Madill437fa652016-05-03 15:13:24 -04005068 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03005069 GL_INVALID_OPERATION,
5070 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
5071 return false;
5072 }
5073 return true;
5074}
5075
5076bool ValidateFlushMappedBufferRangeBase(Context *context,
5077 GLenum target,
5078 GLintptr offset,
5079 GLsizeiptr length)
5080{
5081 if (offset < 0 || length < 0)
5082 {
Jamie Madill437fa652016-05-03 15:13:24 -04005083 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03005084 return false;
5085 }
5086
5087 if (!ValidBufferTarget(context, target))
5088 {
Jamie Madill437fa652016-05-03 15:13:24 -04005089 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03005090 return false;
5091 }
5092
Jamie Madilldfde6ab2016-06-09 07:07:18 -07005093 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03005094
5095 if (buffer == nullptr)
5096 {
Jamie Madill437fa652016-05-03 15:13:24 -04005097 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03005098 return false;
5099 }
5100
5101 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
5102 {
Jamie Madill437fa652016-05-03 15:13:24 -04005103 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03005104 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
5105 return false;
5106 }
5107
5108 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04005109 CheckedNumeric<size_t> checkedOffset(offset);
5110 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03005111
Jamie Madille2e406c2016-06-02 13:04:10 -04005112 if (!checkedSize.IsValid() ||
5113 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03005114 {
Jamie Madill437fa652016-05-03 15:13:24 -04005115 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03005116 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
5117 return false;
5118 }
5119
5120 return true;
5121}
5122
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005123bool ValidateGenerateMipmap(Context *context, GLenum target)
5124{
5125 if (!ValidTextureTarget(context, target))
5126 {
5127 context->handleError(Error(GL_INVALID_ENUM));
5128 return false;
5129 }
5130
5131 Texture *texture = context->getTargetTexture(target);
5132
5133 if (texture == nullptr)
5134 {
5135 context->handleError(Error(GL_INVALID_OPERATION));
5136 return false;
5137 }
5138
5139 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
5140
5141 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
5142 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
5143 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
5144 {
5145 context->handleError(Error(GL_INVALID_OPERATION));
5146 return false;
5147 }
5148
Jamie Madilla3944d42016-07-22 22:13:26 -04005149 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
5150 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
Geoff Langca271392017-04-05 12:30:00 -04005151 const TextureCaps &formatCaps = context->getTextureCaps().get(format.info->sizedInternalFormat);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005152
5153 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
5154 // unsized formats or that are color renderable and filterable. Since we do not track if
5155 // the texture was created with sized or unsized format (only sized formats are stored),
5156 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
5157 // be able to) because they aren't color renderable. Simply do a special case for LUMA
5158 // textures since they're the only texture format that can be created with unsized formats
5159 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
5160 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04005161 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
5162 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005163 {
5164 context->handleError(Error(GL_INVALID_OPERATION));
5165 return false;
5166 }
5167
5168 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04005169 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005170 {
5171 context->handleError(Error(GL_INVALID_OPERATION));
5172 return false;
5173 }
5174
5175 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05005176 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005177 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
5178 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
5179 {
Geoff Lang55482a12016-11-21 16:54:01 -05005180 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03005181 context->handleError(Error(GL_INVALID_OPERATION));
5182 return false;
5183 }
5184
5185 // Cube completeness check
5186 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
5187 {
5188 context->handleError(Error(GL_INVALID_OPERATION));
5189 return false;
5190 }
5191
5192 return true;
5193}
5194
Olli Etuaho41997e72016-03-10 13:38:39 +02005195bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
5196{
5197 return ValidateGenOrDelete(context, n);
5198}
5199
5200bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
5201{
5202 return ValidateGenOrDelete(context, n);
5203}
5204
5205bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
5206{
5207 return ValidateGenOrDelete(context, n);
5208}
5209
5210bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
5211{
5212 return ValidateGenOrDelete(context, n);
5213}
5214
5215bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
5216{
5217 return ValidateGenOrDelete(context, n);
5218}
5219
5220bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
5221{
5222 return ValidateGenOrDelete(context, n);
5223}
5224
5225bool ValidateGenTextures(Context *context, GLint n, GLuint *)
5226{
5227 return ValidateGenOrDelete(context, n);
5228}
5229
5230bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
5231{
5232 return ValidateGenOrDelete(context, n);
5233}
5234
5235bool ValidateGenOrDelete(Context *context, GLint n)
5236{
5237 if (n < 0)
5238 {
Jamie Madill437fa652016-05-03 15:13:24 -04005239 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02005240 return false;
5241 }
5242 return true;
5243}
5244
Geoff Langf41a7152016-09-19 15:11:17 -04005245bool ValidateEnable(Context *context, GLenum cap)
5246{
5247 if (!ValidCap(context, cap, false))
5248 {
5249 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5250 return false;
5251 }
5252
5253 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
5254 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
5255 {
5256 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
5257 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
5258
5259 // We also output an error message to the debugger window if tracing is active, so that
5260 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05005261 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04005262 return false;
5263 }
5264
5265 return true;
5266}
5267
5268bool ValidateDisable(Context *context, GLenum cap)
5269{
5270 if (!ValidCap(context, cap, false))
5271 {
5272 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5273 return false;
5274 }
5275
5276 return true;
5277}
5278
5279bool ValidateIsEnabled(Context *context, GLenum cap)
5280{
5281 if (!ValidCap(context, cap, true))
5282 {
5283 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
5284 return false;
5285 }
5286
5287 return true;
5288}
5289
Geoff Langff5b2d52016-09-07 11:32:23 -04005290bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
5291{
5292 if (!context->getExtensions().robustClientMemory)
5293 {
5294 context->handleError(
5295 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
5296 return false;
5297 }
5298
5299 if (bufSize < 0)
5300 {
5301 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
5302 return false;
5303 }
5304
5305 return true;
5306}
5307
Geoff Lang2e43dbb2016-10-14 12:27:35 -04005308bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
5309{
5310 if (bufSize < numParams)
5311 {
5312 context->handleError(Error(GL_INVALID_OPERATION,
5313 "%u parameters are required but %i were provided.", numParams,
5314 bufSize));
5315 return false;
5316 }
5317
5318 return true;
5319}
5320
Geoff Langff5b2d52016-09-07 11:32:23 -04005321bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
5322 GLenum target,
5323 GLenum attachment,
5324 GLenum pname,
5325 GLsizei *numParams)
5326{
5327 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
Yunchao He33151a52017-04-13 09:58:17 +08005328 if (numParams)
5329 {
5330 *numParams = 1;
5331 }
Geoff Langff5b2d52016-09-07 11:32:23 -04005332
5333 if (!ValidFramebufferTarget(target))
5334 {
5335 context->handleError(Error(GL_INVALID_ENUM));
5336 return false;
5337 }
5338
5339 int clientVersion = context->getClientMajorVersion();
5340
5341 switch (pname)
5342 {
5343 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5344 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5345 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
5346 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
5347 break;
5348
5349 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
5350 if (clientVersion < 3 && !context->getExtensions().sRGB)
5351 {
5352 context->handleError(Error(GL_INVALID_ENUM));
5353 return false;
5354 }
5355 break;
5356
5357 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
5358 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
5359 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
5360 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
5361 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
5362 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
5363 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
5364 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
5365 if (clientVersion < 3)
5366 {
5367 context->handleError(Error(GL_INVALID_ENUM));
5368 return false;
5369 }
5370 break;
5371
5372 default:
5373 context->handleError(Error(GL_INVALID_ENUM));
5374 return false;
5375 }
5376
5377 // Determine if the attachment is a valid enum
5378 switch (attachment)
5379 {
5380 case GL_BACK:
5381 case GL_FRONT:
5382 case GL_DEPTH:
5383 case GL_STENCIL:
5384 case GL_DEPTH_STENCIL_ATTACHMENT:
5385 if (clientVersion < 3)
5386 {
5387 context->handleError(Error(GL_INVALID_ENUM));
5388 return false;
5389 }
5390 break;
5391
5392 case GL_DEPTH_ATTACHMENT:
5393 case GL_STENCIL_ATTACHMENT:
5394 break;
5395
5396 default:
5397 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
5398 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
5399 {
5400 context->handleError(Error(GL_INVALID_ENUM));
5401 return false;
5402 }
5403 break;
5404 }
5405
5406 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
5407 ASSERT(framebuffer);
5408
5409 if (framebuffer->id() == 0)
5410 {
5411 if (clientVersion < 3)
5412 {
5413 context->handleError(Error(GL_INVALID_OPERATION));
5414 return false;
5415 }
5416
5417 switch (attachment)
5418 {
5419 case GL_BACK:
5420 case GL_DEPTH:
5421 case GL_STENCIL:
5422 break;
5423
5424 default:
5425 context->handleError(Error(GL_INVALID_OPERATION));
5426 return false;
5427 }
5428 }
5429 else
5430 {
5431 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
5432 {
5433 // Valid attachment query
5434 }
5435 else
5436 {
5437 switch (attachment)
5438 {
5439 case GL_DEPTH_ATTACHMENT:
5440 case GL_STENCIL_ATTACHMENT:
5441 break;
5442
5443 case GL_DEPTH_STENCIL_ATTACHMENT:
5444 if (!framebuffer->hasValidDepthStencil())
5445 {
5446 context->handleError(Error(GL_INVALID_OPERATION));
5447 return false;
5448 }
5449 break;
5450
5451 default:
5452 context->handleError(Error(GL_INVALID_OPERATION));
5453 return false;
5454 }
5455 }
5456 }
5457
5458 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
5459 if (attachmentObject)
5460 {
5461 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
5462 attachmentObject->type() == GL_TEXTURE ||
5463 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
5464
5465 switch (pname)
5466 {
5467 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5468 if (attachmentObject->type() != GL_RENDERBUFFER &&
5469 attachmentObject->type() != GL_TEXTURE)
5470 {
5471 context->handleError(Error(GL_INVALID_ENUM));
5472 return false;
5473 }
5474 break;
5475
5476 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
5477 if (attachmentObject->type() != GL_TEXTURE)
5478 {
5479 context->handleError(Error(GL_INVALID_ENUM));
5480 return false;
5481 }
5482 break;
5483
5484 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
5485 if (attachmentObject->type() != GL_TEXTURE)
5486 {
5487 context->handleError(Error(GL_INVALID_ENUM));
5488 return false;
5489 }
5490 break;
5491
5492 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
5493 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
5494 {
5495 context->handleError(Error(GL_INVALID_OPERATION));
5496 return false;
5497 }
5498 break;
5499
5500 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
5501 if (attachmentObject->type() != GL_TEXTURE)
5502 {
5503 context->handleError(Error(GL_INVALID_ENUM));
5504 return false;
5505 }
5506 break;
5507
5508 default:
5509 break;
5510 }
5511 }
5512 else
5513 {
5514 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
5515 // is NONE, then querying any other pname will generate INVALID_ENUM.
5516
5517 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
5518 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
5519 // INVALID_OPERATION for all other pnames
5520
5521 switch (pname)
5522 {
5523 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5524 break;
5525
5526 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5527 if (clientVersion < 3)
5528 {
5529 context->handleError(Error(GL_INVALID_ENUM));
5530 return false;
5531 }
5532 break;
5533
5534 default:
5535 if (clientVersion < 3)
5536 {
5537 context->handleError(Error(GL_INVALID_ENUM));
5538 return false;
5539 }
5540 else
5541 {
5542 context->handleError(Error(GL_INVALID_OPERATION));
5543 return false;
5544 }
5545 }
5546 }
5547
5548 return true;
5549}
5550
5551bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5552 GLenum target,
5553 GLenum attachment,
5554 GLenum pname,
5555 GLsizei bufSize,
5556 GLsizei *numParams)
5557{
5558 if (!ValidateRobustEntryPoint(context, bufSize))
5559 {
5560 return false;
5561 }
5562
5563 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5564 {
5565 return false;
5566 }
5567
5568 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5569 {
5570 return false;
5571 }
5572
5573 return true;
5574}
5575
5576bool ValidateGetBufferParameteriv(ValidationContext *context,
5577 GLenum target,
5578 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005579 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005580{
Geoff Langebebe1c2016-10-14 12:01:31 -04005581 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005582}
5583
5584bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5585 GLenum target,
5586 GLenum pname,
5587 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005588 GLsizei *length,
5589 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005590{
5591 if (!ValidateRobustEntryPoint(context, bufSize))
5592 {
5593 return false;
5594 }
5595
Geoff Langebebe1c2016-10-14 12:01:31 -04005596 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005597 {
5598 return false;
5599 }
5600
Geoff Langebebe1c2016-10-14 12:01:31 -04005601 if (!ValidateRobustBufferSize(context, bufSize, *length))
5602 {
5603 return false;
5604 }
5605
5606 return true;
5607}
5608
5609bool ValidateGetBufferParameteri64v(ValidationContext *context,
5610 GLenum target,
5611 GLenum pname,
5612 GLint64 *params)
5613{
5614 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5615}
5616
5617bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5618 GLenum target,
5619 GLenum pname,
5620 GLsizei bufSize,
5621 GLsizei *length,
5622 GLint64 *params)
5623{
5624 if (!ValidateRobustEntryPoint(context, bufSize))
5625 {
5626 return false;
5627 }
5628
5629 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5630 {
5631 return false;
5632 }
5633
5634 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005635 {
5636 return false;
5637 }
5638
5639 return true;
5640}
5641
5642bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5643{
5644 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08005645 if (numParams)
5646 {
5647 *numParams = 1;
5648 }
Geoff Langff5b2d52016-09-07 11:32:23 -04005649
5650 Program *programObject = GetValidProgram(context, program);
5651 if (!programObject)
5652 {
5653 return false;
5654 }
5655
5656 switch (pname)
5657 {
5658 case GL_DELETE_STATUS:
5659 case GL_LINK_STATUS:
5660 case GL_VALIDATE_STATUS:
5661 case GL_INFO_LOG_LENGTH:
5662 case GL_ATTACHED_SHADERS:
5663 case GL_ACTIVE_ATTRIBUTES:
5664 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5665 case GL_ACTIVE_UNIFORMS:
5666 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5667 break;
5668
5669 case GL_PROGRAM_BINARY_LENGTH:
5670 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5671 {
5672 context->handleError(Error(GL_INVALID_ENUM,
5673 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5674 "GL_OES_get_program_binary or ES 3.0."));
5675 return false;
5676 }
5677 break;
5678
5679 case GL_ACTIVE_UNIFORM_BLOCKS:
5680 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5681 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5682 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5683 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5684 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5685 if (context->getClientMajorVersion() < 3)
5686 {
5687 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5688 return false;
5689 }
5690 break;
5691
Yunchao He61afff12017-03-14 15:34:03 +08005692 case GL_PROGRAM_SEPARABLE:
5693 if (context->getClientVersion() < Version(3, 1))
5694 {
5695 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.1."));
5696 return false;
5697 }
5698 break;
5699
Geoff Langff5b2d52016-09-07 11:32:23 -04005700 default:
5701 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5702 return false;
5703 }
5704
5705 return true;
5706}
5707
5708bool ValidateGetProgramivRobustANGLE(Context *context,
5709 GLuint program,
5710 GLenum pname,
5711 GLsizei bufSize,
5712 GLsizei *numParams)
5713{
5714 if (!ValidateRobustEntryPoint(context, bufSize))
5715 {
5716 return false;
5717 }
5718
5719 if (!ValidateGetProgramiv(context, program, pname, numParams))
5720 {
5721 return false;
5722 }
5723
5724 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5725 {
5726 return false;
5727 }
5728
5729 return true;
5730}
5731
Geoff Lang740d9022016-10-07 11:20:52 -04005732bool ValidateGetRenderbufferParameteriv(Context *context,
5733 GLenum target,
5734 GLenum pname,
5735 GLint *params)
5736{
5737 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5738}
5739
5740bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5741 GLenum target,
5742 GLenum pname,
5743 GLsizei bufSize,
5744 GLsizei *length,
5745 GLint *params)
5746{
5747 if (!ValidateRobustEntryPoint(context, bufSize))
5748 {
5749 return false;
5750 }
5751
5752 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5753 {
5754 return false;
5755 }
5756
5757 if (!ValidateRobustBufferSize(context, bufSize, *length))
5758 {
5759 return false;
5760 }
5761
5762 return true;
5763}
5764
Geoff Langd7d0ed32016-10-07 11:33:51 -04005765bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5766{
5767 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5768}
5769
5770bool ValidateGetShaderivRobustANGLE(Context *context,
5771 GLuint shader,
5772 GLenum pname,
5773 GLsizei bufSize,
5774 GLsizei *length,
5775 GLint *params)
5776{
5777 if (!ValidateRobustEntryPoint(context, bufSize))
5778 {
5779 return false;
5780 }
5781
5782 if (!ValidateGetShaderivBase(context, shader, pname, length))
5783 {
5784 return false;
5785 }
5786
5787 if (!ValidateRobustBufferSize(context, bufSize, *length))
5788 {
5789 return false;
5790 }
5791
5792 return true;
5793}
5794
Geoff Langc1984ed2016-10-07 12:41:00 -04005795bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5796{
5797 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5798}
5799
5800bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5801 GLenum target,
5802 GLenum pname,
5803 GLsizei bufSize,
5804 GLsizei *length,
5805 GLfloat *params)
5806{
5807 if (!ValidateRobustEntryPoint(context, bufSize))
5808 {
5809 return false;
5810 }
5811
5812 if (!ValidateGetTexParameterBase(context, target, pname, length))
5813 {
5814 return false;
5815 }
5816
5817 if (!ValidateRobustBufferSize(context, bufSize, *length))
5818 {
5819 return false;
5820 }
5821
5822 return true;
5823}
5824
5825bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5826{
5827 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5828}
5829
5830bool ValidateGetTexParameterivRobustANGLE(Context *context,
5831 GLenum target,
5832 GLenum pname,
5833 GLsizei bufSize,
5834 GLsizei *length,
5835 GLint *params)
5836{
5837 if (!ValidateRobustEntryPoint(context, bufSize))
5838 {
5839 return false;
5840 }
5841
5842 if (!ValidateGetTexParameterBase(context, target, pname, length))
5843 {
5844 return false;
5845 }
5846
5847 if (!ValidateRobustBufferSize(context, bufSize, *length))
5848 {
5849 return false;
5850 }
5851
5852 return true;
5853}
5854
5855bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5856{
5857 return ValidateTexParameterBase(context, target, pname, -1, &param);
5858}
5859
5860bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5861{
5862 return ValidateTexParameterBase(context, target, pname, -1, params);
5863}
5864
5865bool ValidateTexParameterfvRobustANGLE(Context *context,
5866 GLenum target,
5867 GLenum pname,
5868 GLsizei bufSize,
5869 const GLfloat *params)
5870{
5871 if (!ValidateRobustEntryPoint(context, bufSize))
5872 {
5873 return false;
5874 }
5875
5876 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5877}
5878
5879bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5880{
5881 return ValidateTexParameterBase(context, target, pname, -1, &param);
5882}
5883
5884bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5885{
5886 return ValidateTexParameterBase(context, target, pname, -1, params);
5887}
5888
5889bool ValidateTexParameterivRobustANGLE(Context *context,
5890 GLenum target,
5891 GLenum pname,
5892 GLsizei bufSize,
5893 const GLint *params)
5894{
5895 if (!ValidateRobustEntryPoint(context, bufSize))
5896 {
5897 return false;
5898 }
5899
5900 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5901}
5902
5903bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5904{
5905 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5906}
5907
5908bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5909 GLuint sampler,
5910 GLenum pname,
5911 GLuint bufSize,
5912 GLsizei *length,
5913 GLfloat *params)
5914{
5915 if (!ValidateRobustEntryPoint(context, bufSize))
5916 {
5917 return false;
5918 }
5919
5920 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5921 {
5922 return false;
5923 }
5924
5925 if (!ValidateRobustBufferSize(context, bufSize, *length))
5926 {
5927 return false;
5928 }
5929
5930 return true;
5931}
5932
5933bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5934{
5935 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5936}
5937
5938bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5939 GLuint sampler,
5940 GLenum pname,
5941 GLuint bufSize,
5942 GLsizei *length,
5943 GLint *params)
5944{
5945 if (!ValidateRobustEntryPoint(context, bufSize))
5946 {
5947 return false;
5948 }
5949
5950 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5951 {
5952 return false;
5953 }
5954
5955 if (!ValidateRobustBufferSize(context, bufSize, *length))
5956 {
5957 return false;
5958 }
5959
5960 return true;
5961}
5962
5963bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5964{
5965 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5966}
5967
5968bool ValidateSamplerParameterfv(Context *context,
5969 GLuint sampler,
5970 GLenum pname,
5971 const GLfloat *params)
5972{
5973 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5974}
5975
5976bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5977 GLuint sampler,
5978 GLenum pname,
5979 GLsizei bufSize,
5980 const GLfloat *params)
5981{
5982 if (!ValidateRobustEntryPoint(context, bufSize))
5983 {
5984 return false;
5985 }
5986
5987 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5988}
5989
5990bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5991{
5992 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5993}
5994
5995bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5996{
5997 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5998}
5999
6000bool ValidateSamplerParameterivRobustANGLE(Context *context,
6001 GLuint sampler,
6002 GLenum pname,
6003 GLsizei bufSize,
6004 const GLint *params)
6005{
6006 if (!ValidateRobustEntryPoint(context, bufSize))
6007 {
6008 return false;
6009 }
6010
6011 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
6012}
6013
Geoff Lang0b031062016-10-13 14:30:04 -04006014bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
6015{
6016 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6017}
6018
6019bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
6020 GLuint index,
6021 GLenum pname,
6022 GLsizei bufSize,
6023 GLsizei *length,
6024 GLfloat *params)
6025{
6026 if (!ValidateRobustEntryPoint(context, bufSize))
6027 {
6028 return false;
6029 }
6030
6031 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
6032 {
6033 return false;
6034 }
6035
6036 if (!ValidateRobustBufferSize(context, bufSize, *length))
6037 {
6038 return false;
6039 }
6040
6041 return true;
6042}
6043
6044bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
6045{
6046 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
6047}
6048
6049bool ValidateGetVertexAttribivRobustANGLE(Context *context,
6050 GLuint index,
6051 GLenum pname,
6052 GLsizei bufSize,
6053 GLsizei *length,
6054 GLint *params)
6055{
6056 if (!ValidateRobustEntryPoint(context, bufSize))
6057 {
6058 return false;
6059 }
6060
6061 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
6062 {
6063 return false;
6064 }
6065
6066 if (!ValidateRobustBufferSize(context, bufSize, *length))
6067 {
6068 return false;
6069 }
6070
6071 return true;
6072}
6073
6074bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
6075{
6076 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
6077}
6078
6079bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
6080 GLuint index,
6081 GLenum pname,
6082 GLsizei bufSize,
6083 GLsizei *length,
6084 void **pointer)
6085{
6086 if (!ValidateRobustEntryPoint(context, bufSize))
6087 {
6088 return false;
6089 }
6090
6091 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
6092 {
6093 return false;
6094 }
6095
6096 if (!ValidateRobustBufferSize(context, bufSize, *length))
6097 {
6098 return false;
6099 }
6100
6101 return true;
6102}
6103
6104bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
6105{
6106 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
6107}
6108
6109bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
6110 GLuint index,
6111 GLenum pname,
6112 GLsizei bufSize,
6113 GLsizei *length,
6114 GLint *params)
6115{
6116 if (!ValidateRobustEntryPoint(context, bufSize))
6117 {
6118 return false;
6119 }
6120
6121 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
6122 {
6123 return false;
6124 }
6125
6126 if (!ValidateRobustBufferSize(context, bufSize, *length))
6127 {
6128 return false;
6129 }
6130
6131 return true;
6132}
6133
6134bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
6135{
6136 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
6137}
6138
6139bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
6140 GLuint index,
6141 GLenum pname,
6142 GLsizei bufSize,
6143 GLsizei *length,
6144 GLuint *params)
6145{
6146 if (!ValidateRobustEntryPoint(context, bufSize))
6147 {
6148 return false;
6149 }
6150
6151 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
6152 {
6153 return false;
6154 }
6155
6156 if (!ValidateRobustBufferSize(context, bufSize, *length))
6157 {
6158 return false;
6159 }
6160
6161 return true;
6162}
6163
Geoff Lang6899b872016-10-14 11:30:13 -04006164bool ValidateGetActiveUniformBlockiv(Context *context,
6165 GLuint program,
6166 GLuint uniformBlockIndex,
6167 GLenum pname,
6168 GLint *params)
6169{
6170 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
6171}
6172
6173bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
6174 GLuint program,
6175 GLuint uniformBlockIndex,
6176 GLenum pname,
6177 GLsizei bufSize,
6178 GLsizei *length,
6179 GLint *params)
6180{
6181 if (!ValidateRobustEntryPoint(context, bufSize))
6182 {
6183 return false;
6184 }
6185
6186 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
6187 {
6188 return false;
6189 }
6190
6191 if (!ValidateRobustBufferSize(context, bufSize, *length))
6192 {
6193 return false;
6194 }
6195
6196 return true;
6197}
6198
Geoff Lang0a9661f2016-10-20 10:59:20 -07006199bool ValidateGetInternalFormativ(Context *context,
6200 GLenum target,
6201 GLenum internalformat,
6202 GLenum pname,
6203 GLsizei bufSize,
6204 GLint *params)
6205{
6206 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
6207 nullptr);
6208}
6209
6210bool ValidateGetInternalFormativRobustANGLE(Context *context,
6211 GLenum target,
6212 GLenum internalformat,
6213 GLenum pname,
6214 GLsizei bufSize,
6215 GLsizei *length,
6216 GLint *params)
6217{
6218 if (!ValidateRobustEntryPoint(context, bufSize))
6219 {
6220 return false;
6221 }
6222
6223 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
6224 {
6225 return false;
6226 }
6227
6228 if (!ValidateRobustBufferSize(context, bufSize, *length))
6229 {
6230 return false;
6231 }
6232
6233 return true;
6234}
6235
Shao80957d92017-02-20 21:25:59 +08006236bool ValidateVertexFormatBase(ValidationContext *context,
6237 GLuint attribIndex,
6238 GLint size,
6239 GLenum type,
6240 GLboolean pureInteger)
6241{
6242 const Caps &caps = context->getCaps();
6243 if (attribIndex >= caps.maxVertexAttributes)
6244 {
6245 context->handleError(
6246 Error(GL_INVALID_VALUE, "attribindex must be smaller than MAX_VERTEX_ATTRIBS."));
6247 return false;
6248 }
6249
6250 if (size < 1 || size > 4)
6251 {
6252 context->handleError(Error(GL_INVALID_VALUE, "size must be between one and four."));
6253 }
6254
6255 switch (type)
6256 {
6257 case GL_BYTE:
6258 case GL_UNSIGNED_BYTE:
6259 case GL_SHORT:
6260 case GL_UNSIGNED_SHORT:
6261 break;
6262
6263 case GL_INT:
6264 case GL_UNSIGNED_INT:
6265 if (context->getClientMajorVersion() < 3)
6266 {
6267 context->handleError(
6268 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
6269 return false;
6270 }
6271 break;
6272
6273 case GL_FIXED:
6274 case GL_FLOAT:
6275 if (pureInteger)
6276 {
6277 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
6278 return false;
6279 }
6280 break;
6281
6282 case GL_HALF_FLOAT:
6283 if (context->getClientMajorVersion() < 3)
6284 {
6285 context->handleError(
6286 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
6287 return false;
6288 }
6289 if (pureInteger)
6290 {
6291 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
6292 return false;
6293 }
6294 break;
6295
6296 case GL_INT_2_10_10_10_REV:
6297 case GL_UNSIGNED_INT_2_10_10_10_REV:
6298 if (context->getClientMajorVersion() < 3)
6299 {
6300 context->handleError(
6301 Error(GL_INVALID_ENUM, "Vertex type not supported before OpenGL ES 3.0."));
6302 return false;
6303 }
6304 if (pureInteger)
6305 {
6306 context->handleError(Error(GL_INVALID_ENUM, "Type is not integer."));
6307 return false;
6308 }
6309 if (size != 4)
6310 {
6311 context->handleError(Error(GL_INVALID_OPERATION,
6312 "Type is INT_2_10_10_10_REV or "
6313 "UNSIGNED_INT_2_10_10_10_REV and size is not 4."));
6314 return false;
6315 }
6316 break;
6317
6318 default:
6319 context->handleError(Error(GL_INVALID_ENUM, "Invalid vertex type."));
6320 return false;
6321 }
6322
6323 return true;
6324}
6325
Geoff Lang76e65652017-03-27 14:58:02 -04006326// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
6327// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
6328// specified clear value and the type of a buffer that is being cleared generates an
6329// INVALID_OPERATION error instead of producing undefined results
6330bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
6331 GLint drawbuffer,
6332 const GLenum *validComponentTypes,
6333 size_t validComponentTypeCount)
6334{
6335 const FramebufferAttachment *attachment =
6336 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
6337 if (attachment)
6338 {
6339 GLenum componentType = attachment->getFormat().info->componentType;
6340 const GLenum *end = validComponentTypes + validComponentTypeCount;
6341 if (std::find(validComponentTypes, end, componentType) == end)
6342 {
6343 context->handleError(
6344 Error(GL_INVALID_OPERATION,
6345 "No defined conversion between clear value and attachment format."));
6346 return false;
6347 }
6348 }
6349
6350 return true;
6351}
6352
Corentin Wallezb2931602017-04-11 15:58:57 -04006353bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
6354 GLsizei imageSize,
6355 GLsizei dataSize)
6356{
6357 if (!ValidateRobustEntryPoint(context, dataSize))
6358 {
6359 return false;
6360 }
6361
6362 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
6363 if (pixelUnpackBuffer == nullptr)
6364 {
6365 if (dataSize < imageSize)
6366 {
6367 context->handleError(
6368 Error(GL_INVALID_OPERATION, "dataSize must be at least %i.", imageSize));
6369 }
6370 }
6371 return true;
6372}
6373
Jamie Madillc29968b2016-01-20 11:17:23 -05006374} // namespace gl