blob: 74037b291ae5d6b29e77783301eccf827a23c3a1 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES2.h"
12#include "libANGLE/validationES3.h"
13#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040014#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Texture.h"
16#include "libANGLE/Framebuffer.h"
17#include "libANGLE/FramebufferAttachment.h"
18#include "libANGLE/formatutils.h"
Geoff Langa8406172015-07-21 16:53:39 -040019#include "libANGLE/Image.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/Query.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050021#include "libANGLE/Program.h"
22#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/TransformFeedback.h"
24#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025
26#include "common/mathutil.h"
27#include "common/utilities.h"
28
Jamie Madille2e406c2016-06-02 13:04:10 -040029using namespace angle;
30
Geoff Lange8ebe7f2013-08-05 15:03:13 -040031namespace gl
32{
Jamie Madille79b1e12015-11-04 16:36:37 -050033const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
34
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Corentin Wallez92db6942016-12-09 13:10:36 -050037bool ValidateDrawAttribs(ValidationContext *context,
38 GLint primcount,
39 GLint maxVertex,
40 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040041{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070042 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040043 const gl::Program *program = state.getProgram();
44
Corentin Wallez327411e2016-12-09 11:09:17 -050045 bool webglCompatibility = context->getExtensions().webglCompatibility;
46
He Yunchaoced53ae2016-11-29 15:00:51 +080047 const VertexArray *vao = state.getVertexArray();
48 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080049 const auto &vertexBindings = vao->getVertexBindings();
He Yunchaoced53ae2016-11-29 15:00:51 +080050 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040051 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
52 {
53 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallezfd456442016-12-21 17:57:00 -050054 if (!program->isAttribLocationActive(attributeIndex) || !attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040055 {
Corentin Wallezfd456442016-12-21 17:57:00 -050056 continue;
57 }
Jamie Madill1ca74672015-07-21 15:14:11 -040058
Jiawei-Shao2597fb62016-12-09 16:38:02 +080059 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
Corentin Wallezfd456442016-12-21 17:57:00 -050060 // If we have no buffer, then we either get an error, or there are no more checks to be done.
Jiawei-Shao2597fb62016-12-09 16:38:02 +080061 gl::Buffer *buffer = binding.buffer.get();
Corentin Wallezfd456442016-12-21 17:57:00 -050062 if (!buffer)
63 {
Geoff Langfeb8c682017-02-13 16:07:35 -050064 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050065 {
66 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050067 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
68 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
69 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
70 // error.
Corentin Wallez327411e2016-12-09 11:09:17 -050071 context->handleError(
72 Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer."));
Corentin Wallezfd456442016-12-21 17:57:00 -050073 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050074 }
Corentin Wallezfd456442016-12-21 17:57:00 -050075 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040076 {
77 // This is an application error that would normally result in a crash,
78 // but we catch it and return an error
Corentin Wallezfd456442016-12-21 17:57:00 -050079 context->handleError(
80 Error(GL_INVALID_OPERATION,
81 "An enabled vertex array has no buffer and no pointer."));
Jamie Madill1ca74672015-07-21 15:14:11 -040082 return false;
83 }
Corentin Wallezfd456442016-12-21 17:57:00 -050084 continue;
85 }
86
87 // If we're drawing zero vertices, we have enough data.
88 if (vertexCount <= 0 || primcount <= 0)
89 {
90 continue;
91 }
92
93 GLint maxVertexElement = 0;
Jiawei-Shao2597fb62016-12-09 16:38:02 +080094 if (binding.divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -050095 {
96 maxVertexElement = maxVertex;
97 }
98 else
99 {
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800100 maxVertexElement = (primcount - 1) / binding.divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500101 }
102
103 // We do manual overflow checks here instead of using safe_math.h because it was
104 // a bottleneck. Thanks to some properties of GL we know inequalities that can
105 // help us make the overflow checks faster.
106
107 // The max possible attribSize is 16 for a vector of 4 32 bit values.
108 constexpr uint64_t kMaxAttribSize = 16;
109 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
110 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
111
112 // We know attribStride is given as a GLsizei which is typedefed to int.
113 // We also know an upper bound for attribSize.
114 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800115 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500116 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
117 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
118
119 // Computing the max offset using uint64_t without attrib.offset is overflow
120 // safe. Note: Last vertex element does not take the full stride!
121 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
122 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
123
124 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800125 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
126 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500127 {
128 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
129 return false;
130 }
131 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
132
133 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
134 // We can return INVALID_OPERATION if our vertex attribute does not have
135 // enough backing data.
136 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
137 {
138 context->handleError(Error(GL_INVALID_OPERATION,
139 "Vertex buffer is not big enough for the draw call"));
140 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400141 }
142 }
143
144 return true;
145}
146
Geoff Langf607c602016-09-21 11:46:48 -0400147bool ValidReadPixelsFormatType(ValidationContext *context,
148 GLenum framebufferComponentType,
149 GLenum format,
150 GLenum type)
151{
152 switch (framebufferComponentType)
153 {
154 case GL_UNSIGNED_NORMALIZED:
155 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
156 // ReadPixels with BGRA even if the extension is not present
157 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
158 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
159 type == GL_UNSIGNED_BYTE);
160
161 case GL_SIGNED_NORMALIZED:
162 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
163
164 case GL_INT:
165 return (format == GL_RGBA_INTEGER && type == GL_INT);
166
167 case GL_UNSIGNED_INT:
168 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
169
170 case GL_FLOAT:
171 return (format == GL_RGBA && type == GL_FLOAT);
172
173 default:
174 UNREACHABLE();
175 return false;
176 }
177}
178
Geoff Langf41a7152016-09-19 15:11:17 -0400179bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500180{
181 switch (cap)
182 {
Geoff Langf41a7152016-09-19 15:11:17 -0400183 // EXT_multisample_compatibility
184 case GL_MULTISAMPLE_EXT:
185 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
186 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300187
Geoff Langf41a7152016-09-19 15:11:17 -0400188 case GL_CULL_FACE:
189 case GL_POLYGON_OFFSET_FILL:
190 case GL_SAMPLE_ALPHA_TO_COVERAGE:
191 case GL_SAMPLE_COVERAGE:
192 case GL_SCISSOR_TEST:
193 case GL_STENCIL_TEST:
194 case GL_DEPTH_TEST:
195 case GL_BLEND:
196 case GL_DITHER:
197 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500198
Geoff Langf41a7152016-09-19 15:11:17 -0400199 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
200 case GL_RASTERIZER_DISCARD:
201 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500202
Geoff Langf41a7152016-09-19 15:11:17 -0400203 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
204 case GL_DEBUG_OUTPUT:
205 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500206
Geoff Langf41a7152016-09-19 15:11:17 -0400207 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
208 return queryOnly && context->getExtensions().bindGeneratesResource;
209
Geoff Langfeb8c682017-02-13 16:07:35 -0500210 case GL_CLIENT_ARRAYS_ANGLE:
211 return queryOnly && context->getExtensions().clientArrays;
212
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700213 case GL_FRAMEBUFFER_SRGB_EXT:
214 return context->getExtensions().sRGBWriteControl;
215
Geoff Lang3b573612016-10-31 14:08:10 -0400216 case GL_SAMPLE_MASK:
Geoff Lang3b573612016-10-31 14:08:10 -0400217 return context->getClientVersion() >= Version(3, 1);
218
Jamie Madille08a1d32017-03-07 17:24:06 -0500219 case GL_CONTEXT_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
220 return queryOnly && context->getExtensions().robustResourceInitialization;
221
Geoff Langf41a7152016-09-19 15:11:17 -0400222 default:
223 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500224 }
225}
226
Geoff Lang62fce5b2016-09-30 10:46:35 -0400227bool ValidateReadPixelsBase(ValidationContext *context,
228 GLint x,
229 GLint y,
230 GLsizei width,
231 GLsizei height,
232 GLenum format,
233 GLenum type,
234 GLsizei bufSize,
235 GLsizei *length,
236 GLvoid *pixels)
237{
238 if (length != nullptr)
239 {
240 *length = 0;
241 }
242
243 if (width < 0 || height < 0)
244 {
245 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
246 return false;
247 }
248
249 auto readFramebuffer = context->getGLState().getReadFramebuffer();
250
251 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
252 {
253 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
254 return false;
255 }
256
257 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
258 {
259 context->handleError(Error(GL_INVALID_OPERATION));
260 return false;
261 }
262
263 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
264 ASSERT(framebuffer);
265
266 if (framebuffer->getReadBufferState() == GL_NONE)
267 {
268 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
269 return false;
270 }
271
272 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500273 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
274 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
275 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
276 // situation is an application error that would lead to a crash in ANGLE.
277 if (readBuffer == nullptr)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400278 {
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500279 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
Geoff Lang62fce5b2016-09-30 10:46:35 -0400280 return false;
281 }
282
283 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
284 GLenum currentType = framebuffer->getImplementationColorReadType();
285 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
286
287 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
288 bool validFormatTypeCombination =
289 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
290
291 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
292 {
293 context->handleError(Error(GL_INVALID_OPERATION));
294 return false;
295 }
296
297 // Check for pixel pack buffer related API errors
298 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
299 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
300 {
301 // ...the buffer object's data store is currently mapped.
302 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
303 return false;
304 }
305
306 // .. the data would be packed to the buffer object such that the memory writes required
307 // would exceed the data store size.
308 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
309 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
310 const gl::Extents size(width, height, 1);
311 const auto &pack = context->getGLState().getPackState();
312
313 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
314 if (endByteOrErr.isError())
315 {
316 context->handleError(endByteOrErr.getError());
317 return false;
318 }
319
320 size_t endByte = endByteOrErr.getResult();
321 if (bufSize >= 0)
322 {
323
324 if (static_cast<size_t>(bufSize) < endByte)
325 {
326 context->handleError(
327 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
328 return false;
329 }
330 }
331
332 if (pixelPackBuffer != nullptr)
333 {
334 CheckedNumeric<size_t> checkedEndByte(endByte);
335 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
336 checkedEndByte += checkedOffset;
337
338 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
339 {
340 // Overflow past the end of the buffer
341 context->handleError(
342 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
343 return false;
344 }
345 }
346
347 if (length != nullptr)
348 {
349 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
350 {
351 context->handleError(
352 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
353 return false;
354 }
355
356 *length = static_cast<GLsizei>(endByte);
357 }
358
359 return true;
360}
361
Geoff Lang740d9022016-10-07 11:20:52 -0400362bool ValidateGetRenderbufferParameterivBase(Context *context,
363 GLenum target,
364 GLenum pname,
365 GLsizei *length)
366{
367 if (length)
368 {
369 *length = 0;
370 }
371
372 if (target != GL_RENDERBUFFER)
373 {
374 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
375 return false;
376 }
377
378 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
379 if (renderbuffer == nullptr)
380 {
381 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
382 return false;
383 }
384
385 switch (pname)
386 {
387 case GL_RENDERBUFFER_WIDTH:
388 case GL_RENDERBUFFER_HEIGHT:
389 case GL_RENDERBUFFER_INTERNAL_FORMAT:
390 case GL_RENDERBUFFER_RED_SIZE:
391 case GL_RENDERBUFFER_GREEN_SIZE:
392 case GL_RENDERBUFFER_BLUE_SIZE:
393 case GL_RENDERBUFFER_ALPHA_SIZE:
394 case GL_RENDERBUFFER_DEPTH_SIZE:
395 case GL_RENDERBUFFER_STENCIL_SIZE:
396 break;
397
398 case GL_RENDERBUFFER_SAMPLES_ANGLE:
399 if (!context->getExtensions().framebufferMultisample)
400 {
401 context->handleError(
402 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
403 return false;
404 }
405 break;
406
407 default:
408 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
409 return false;
410 }
411
412 if (length)
413 {
414 *length = 1;
415 }
416 return true;
417}
418
Geoff Langd7d0ed32016-10-07 11:33:51 -0400419bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
420{
421 if (length)
422 {
423 *length = 0;
424 }
425
426 if (GetValidShader(context, shader) == nullptr)
427 {
428 return false;
429 }
430
431 switch (pname)
432 {
433 case GL_SHADER_TYPE:
434 case GL_DELETE_STATUS:
435 case GL_COMPILE_STATUS:
436 case GL_INFO_LOG_LENGTH:
437 case GL_SHADER_SOURCE_LENGTH:
438 break;
439
440 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
441 if (!context->getExtensions().translatedShaderSource)
442 {
443 context->handleError(
444 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
445 return false;
446 }
447 break;
448
449 default:
450 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
451 return false;
452 }
453
454 if (length)
455 {
456 *length = 1;
457 }
458 return true;
459}
460
Geoff Langc1984ed2016-10-07 12:41:00 -0400461bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
462{
463 if (length)
464 {
465 *length = 0;
466 }
467
468 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
469 {
470 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
471 return false;
472 }
473
474 if (context->getTargetTexture(target) == nullptr)
475 {
476 // Should only be possible for external textures
477 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
478 return false;
479 }
480
481 switch (pname)
482 {
483 case GL_TEXTURE_MAG_FILTER:
484 case GL_TEXTURE_MIN_FILTER:
485 case GL_TEXTURE_WRAP_S:
486 case GL_TEXTURE_WRAP_T:
487 break;
488
489 case GL_TEXTURE_USAGE_ANGLE:
490 if (!context->getExtensions().textureUsage)
491 {
492 context->handleError(
493 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
494 return false;
495 }
496 break;
497
498 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
499 if (!context->getExtensions().textureFilterAnisotropic)
500 {
501 context->handleError(
502 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
503 return false;
504 }
505 break;
506
507 case GL_TEXTURE_IMMUTABLE_FORMAT:
508 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
509 {
510 context->handleError(
511 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
512 return false;
513 }
514 break;
515
516 case GL_TEXTURE_WRAP_R:
517 case GL_TEXTURE_IMMUTABLE_LEVELS:
518 case GL_TEXTURE_SWIZZLE_R:
519 case GL_TEXTURE_SWIZZLE_G:
520 case GL_TEXTURE_SWIZZLE_B:
521 case GL_TEXTURE_SWIZZLE_A:
522 case GL_TEXTURE_BASE_LEVEL:
523 case GL_TEXTURE_MAX_LEVEL:
524 case GL_TEXTURE_MIN_LOD:
525 case GL_TEXTURE_MAX_LOD:
526 case GL_TEXTURE_COMPARE_MODE:
527 case GL_TEXTURE_COMPARE_FUNC:
528 if (context->getClientMajorVersion() < 3)
529 {
530 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
531 return false;
532 }
533 break;
534
Geoff Lang81c6b572016-10-19 14:07:52 -0700535 case GL_TEXTURE_SRGB_DECODE_EXT:
536 if (!context->getExtensions().textureSRGBDecode)
537 {
538 context->handleError(
539 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
540 return false;
541 }
542 break;
543
Geoff Langc1984ed2016-10-07 12:41:00 -0400544 default:
545 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
546 return false;
547 }
548
549 if (length)
550 {
551 *length = 1;
552 }
553 return true;
554}
555
556template <typename ParamType>
557bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
558{
559 switch (ConvertToGLenum(params[0]))
560 {
561 case GL_CLAMP_TO_EDGE:
562 break;
563
564 case GL_REPEAT:
565 case GL_MIRRORED_REPEAT:
566 if (isExternalTextureTarget)
567 {
568 // OES_EGL_image_external specifies this error.
569 context->handleError(Error(
570 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
571 return false;
572 }
573 break;
574
575 default:
576 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
577 return false;
578 }
579
580 return true;
581}
582
583template <typename ParamType>
584bool ValidateTextureMinFilterValue(Context *context,
585 ParamType *params,
586 bool isExternalTextureTarget)
587{
588 switch (ConvertToGLenum(params[0]))
589 {
590 case GL_NEAREST:
591 case GL_LINEAR:
592 break;
593
594 case GL_NEAREST_MIPMAP_NEAREST:
595 case GL_LINEAR_MIPMAP_NEAREST:
596 case GL_NEAREST_MIPMAP_LINEAR:
597 case GL_LINEAR_MIPMAP_LINEAR:
598 if (isExternalTextureTarget)
599 {
600 // OES_EGL_image_external specifies this error.
601 context->handleError(
602 Error(GL_INVALID_ENUM,
603 "external textures only support NEAREST and LINEAR filtering"));
604 return false;
605 }
606 break;
607
608 default:
609 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
610 return false;
611 }
612
613 return true;
614}
615
616template <typename ParamType>
617bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
618{
619 switch (ConvertToGLenum(params[0]))
620 {
621 case GL_NEAREST:
622 case GL_LINEAR:
623 break;
624
625 default:
626 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
627 return false;
628 }
629
630 return true;
631}
632
633template <typename ParamType>
634bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
635{
636 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
637 switch (ConvertToGLenum(params[0]))
638 {
639 case GL_NONE:
640 case GL_COMPARE_REF_TO_TEXTURE:
641 break;
642
643 default:
644 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
645 return false;
646 }
647
648 return true;
649}
650
651template <typename ParamType>
652bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
653{
654 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
655 switch (ConvertToGLenum(params[0]))
656 {
657 case GL_LEQUAL:
658 case GL_GEQUAL:
659 case GL_LESS:
660 case GL_GREATER:
661 case GL_EQUAL:
662 case GL_NOTEQUAL:
663 case GL_ALWAYS:
664 case GL_NEVER:
665 break;
666
667 default:
668 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
669 return false;
670 }
671
672 return true;
673}
674
675template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700676bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
677{
678 if (!context->getExtensions().textureSRGBDecode)
679 {
680 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
681 return false;
682 }
683
684 switch (ConvertToGLenum(params[0]))
685 {
686 case GL_DECODE_EXT:
687 case GL_SKIP_DECODE_EXT:
688 break;
689
690 default:
691 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
692 return false;
693 }
694
695 return true;
696}
697
698template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400699bool ValidateTexParameterBase(Context *context,
700 GLenum target,
701 GLenum pname,
702 GLsizei bufSize,
703 ParamType *params)
704{
705 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
706 {
707 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
708 return false;
709 }
710
711 if (context->getTargetTexture(target) == nullptr)
712 {
713 // Should only be possible for external textures
714 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
715 return false;
716 }
717
718 const GLsizei minBufSize = 1;
719 if (bufSize >= 0 && bufSize < minBufSize)
720 {
721 context->handleError(
722 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
723 return false;
724 }
725
726 switch (pname)
727 {
728 case GL_TEXTURE_WRAP_R:
729 case GL_TEXTURE_SWIZZLE_R:
730 case GL_TEXTURE_SWIZZLE_G:
731 case GL_TEXTURE_SWIZZLE_B:
732 case GL_TEXTURE_SWIZZLE_A:
733 case GL_TEXTURE_BASE_LEVEL:
734 case GL_TEXTURE_MAX_LEVEL:
735 case GL_TEXTURE_COMPARE_MODE:
736 case GL_TEXTURE_COMPARE_FUNC:
737 case GL_TEXTURE_MIN_LOD:
738 case GL_TEXTURE_MAX_LOD:
739 if (context->getClientMajorVersion() < 3)
740 {
741 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
742 return false;
743 }
744 if (target == GL_TEXTURE_EXTERNAL_OES &&
745 !context->getExtensions().eglImageExternalEssl3)
746 {
747 context->handleError(Error(GL_INVALID_ENUM,
748 "ES3 texture parameters are not available without "
749 "GL_OES_EGL_image_external_essl3."));
750 return false;
751 }
752 break;
753
754 default:
755 break;
756 }
757
758 switch (pname)
759 {
760 case GL_TEXTURE_WRAP_S:
761 case GL_TEXTURE_WRAP_T:
762 case GL_TEXTURE_WRAP_R:
763 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
764 {
765 return false;
766 }
767 break;
768
769 case GL_TEXTURE_MIN_FILTER:
770 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
771 {
772 return false;
773 }
774 break;
775
776 case GL_TEXTURE_MAG_FILTER:
777 if (!ValidateTextureMagFilterValue(context, params))
778 {
779 return false;
780 }
781 break;
782
783 case GL_TEXTURE_USAGE_ANGLE:
784 switch (ConvertToGLenum(params[0]))
785 {
786 case GL_NONE:
787 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
788 break;
789
790 default:
791 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
792 return false;
793 }
794 break;
795
796 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
797 if (!context->getExtensions().textureFilterAnisotropic)
798 {
799 context->handleError(
800 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
801 return false;
802 }
803
804 // we assume the parameter passed to this validation method is truncated, not rounded
805 if (params[0] < 1)
806 {
807 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
808 return false;
809 }
810 break;
811
812 case GL_TEXTURE_MIN_LOD:
813 case GL_TEXTURE_MAX_LOD:
814 // any value is permissible
815 break;
816
817 case GL_TEXTURE_COMPARE_MODE:
818 if (!ValidateTextureCompareModeValue(context, params))
819 {
820 return false;
821 }
822 break;
823
824 case GL_TEXTURE_COMPARE_FUNC:
825 if (!ValidateTextureCompareFuncValue(context, params))
826 {
827 return false;
828 }
829 break;
830
831 case GL_TEXTURE_SWIZZLE_R:
832 case GL_TEXTURE_SWIZZLE_G:
833 case GL_TEXTURE_SWIZZLE_B:
834 case GL_TEXTURE_SWIZZLE_A:
835 switch (ConvertToGLenum(params[0]))
836 {
837 case GL_RED:
838 case GL_GREEN:
839 case GL_BLUE:
840 case GL_ALPHA:
841 case GL_ZERO:
842 case GL_ONE:
843 break;
844
845 default:
846 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
847 return false;
848 }
849 break;
850
851 case GL_TEXTURE_BASE_LEVEL:
852 if (params[0] < 0)
853 {
854 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
855 return false;
856 }
857 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
858 {
859 context->handleError(
860 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
861 return false;
862 }
863 break;
864
865 case GL_TEXTURE_MAX_LEVEL:
866 if (params[0] < 0)
867 {
868 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
869 return false;
870 }
871 break;
872
Geoff Lang3b573612016-10-31 14:08:10 -0400873 case GL_DEPTH_STENCIL_TEXTURE_MODE:
874 if (context->getClientVersion() < Version(3, 1))
875 {
876 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
877 return false;
878 }
Geoff Lang9f090372016-12-02 10:20:43 -0500879 switch (ConvertToGLenum(params[0]))
880 {
881 case GL_DEPTH_COMPONENT:
882 case GL_STENCIL_INDEX:
883 break;
884
885 default:
886 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
887 return false;
888 }
Geoff Lang3b573612016-10-31 14:08:10 -0400889 break;
890
Geoff Lang81c6b572016-10-19 14:07:52 -0700891 case GL_TEXTURE_SRGB_DECODE_EXT:
892 if (!ValidateTextureSRGBDecodeValue(context, params))
893 {
894 return false;
895 }
896 break;
897
Geoff Langc1984ed2016-10-07 12:41:00 -0400898 default:
899 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
900 return false;
901 }
902
903 return true;
904}
905
906template <typename ParamType>
907bool ValidateSamplerParameterBase(Context *context,
908 GLuint sampler,
909 GLenum pname,
910 GLsizei bufSize,
911 ParamType *params)
912{
913 if (context->getClientMajorVersion() < 3)
914 {
915 context->handleError(
916 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
917 return false;
918 }
919
920 if (!context->isSampler(sampler))
921 {
922 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
923 return false;
924 }
925
926 const GLsizei minBufSize = 1;
927 if (bufSize >= 0 && bufSize < minBufSize)
928 {
929 context->handleError(
930 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
931 return false;
932 }
933
934 switch (pname)
935 {
936 case GL_TEXTURE_WRAP_S:
937 case GL_TEXTURE_WRAP_T:
938 case GL_TEXTURE_WRAP_R:
939 if (!ValidateTextureWrapModeValue(context, params, false))
940 {
941 return false;
942 }
943 break;
944
945 case GL_TEXTURE_MIN_FILTER:
946 if (!ValidateTextureMinFilterValue(context, params, false))
947 {
948 return false;
949 }
950 break;
951
952 case GL_TEXTURE_MAG_FILTER:
953 if (!ValidateTextureMagFilterValue(context, params))
954 {
955 return false;
956 }
957 break;
958
959 case GL_TEXTURE_MIN_LOD:
960 case GL_TEXTURE_MAX_LOD:
961 // any value is permissible
962 break;
963
964 case GL_TEXTURE_COMPARE_MODE:
965 if (!ValidateTextureCompareModeValue(context, params))
966 {
967 return false;
968 }
969 break;
970
971 case GL_TEXTURE_COMPARE_FUNC:
972 if (!ValidateTextureCompareFuncValue(context, params))
973 {
974 return false;
975 }
976 break;
977
Geoff Lang81c6b572016-10-19 14:07:52 -0700978 case GL_TEXTURE_SRGB_DECODE_EXT:
979 if (!ValidateTextureSRGBDecodeValue(context, params))
980 {
981 return false;
982 }
983 break;
984
Geoff Langc1984ed2016-10-07 12:41:00 -0400985 default:
986 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
987 return false;
988 }
989
990 return true;
991}
992
993bool ValidateGetSamplerParameterBase(Context *context,
994 GLuint sampler,
995 GLenum pname,
996 GLsizei *length)
997{
998 if (length)
999 {
1000 *length = 0;
1001 }
1002
1003 if (context->getClientMajorVersion() < 3)
1004 {
1005 context->handleError(
1006 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1007 return false;
1008 }
1009
1010 if (!context->isSampler(sampler))
1011 {
1012 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
1013 return false;
1014 }
1015
1016 switch (pname)
1017 {
1018 case GL_TEXTURE_WRAP_S:
1019 case GL_TEXTURE_WRAP_T:
1020 case GL_TEXTURE_WRAP_R:
1021 case GL_TEXTURE_MIN_FILTER:
1022 case GL_TEXTURE_MAG_FILTER:
1023 case GL_TEXTURE_MIN_LOD:
1024 case GL_TEXTURE_MAX_LOD:
1025 case GL_TEXTURE_COMPARE_MODE:
1026 case GL_TEXTURE_COMPARE_FUNC:
1027 break;
1028
Geoff Lang81c6b572016-10-19 14:07:52 -07001029 case GL_TEXTURE_SRGB_DECODE_EXT:
1030 if (!context->getExtensions().textureSRGBDecode)
1031 {
1032 context->handleError(
1033 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
1034 return false;
1035 }
1036 break;
1037
Geoff Langc1984ed2016-10-07 12:41:00 -04001038 default:
1039 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1040 return false;
1041 }
1042
1043 if (length)
1044 {
1045 *length = 1;
1046 }
1047 return true;
1048}
1049
Geoff Lang0b031062016-10-13 14:30:04 -04001050bool ValidateGetVertexAttribBase(Context *context,
1051 GLuint index,
1052 GLenum pname,
1053 GLsizei *length,
1054 bool pointer,
1055 bool pureIntegerEntryPoint)
1056{
1057 if (length)
1058 {
1059 *length = 0;
1060 }
1061
1062 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1063 {
1064 context->handleError(
1065 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1066 return false;
1067 }
1068
1069 if (index >= context->getCaps().maxVertexAttributes)
1070 {
1071 context->handleError(Error(
1072 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1073 return false;
1074 }
1075
1076 if (pointer)
1077 {
1078 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1079 {
1080 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1081 return false;
1082 }
1083 }
1084 else
1085 {
1086 switch (pname)
1087 {
1088 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1089 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1090 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1091 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1092 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1093 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1094 case GL_CURRENT_VERTEX_ATTRIB:
1095 break;
1096
1097 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1098 static_assert(
1099 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1100 "ANGLE extension enums not equal to GL enums.");
1101 if (context->getClientMajorVersion() < 3 &&
1102 !context->getExtensions().instancedArrays)
1103 {
1104 context->handleError(Error(GL_INVALID_ENUM,
1105 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1106 "3.0 or GL_ANGLE_instanced_arrays."));
1107 return false;
1108 }
1109 break;
1110
1111 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1112 if (context->getClientMajorVersion() < 3)
1113 {
1114 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1115 return false;
1116 }
1117 break;
1118
1119 default:
1120 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1121 return false;
1122 }
1123 }
1124
1125 if (length)
1126 {
1127 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1128 {
1129 *length = 4;
1130 }
1131 else
1132 {
1133 *length = 1;
1134 }
1135 }
1136
1137 return true;
1138}
1139
Geoff Lang6899b872016-10-14 11:30:13 -04001140bool ValidateGetActiveUniformBlockivBase(Context *context,
1141 GLuint program,
1142 GLuint uniformBlockIndex,
1143 GLenum pname,
1144 GLsizei *length)
1145{
1146 if (length)
1147 {
1148 *length = 0;
1149 }
1150
1151 if (context->getClientMajorVersion() < 3)
1152 {
1153 context->handleError(
1154 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1155 return false;
1156 }
1157
1158 Program *programObject = GetValidProgram(context, program);
1159 if (!programObject)
1160 {
1161 return false;
1162 }
1163
1164 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1165 {
1166 context->handleError(
1167 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1168 return false;
1169 }
1170
1171 switch (pname)
1172 {
1173 case GL_UNIFORM_BLOCK_BINDING:
1174 case GL_UNIFORM_BLOCK_DATA_SIZE:
1175 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1176 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1177 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1178 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1179 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1180 break;
1181
1182 default:
1183 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1184 return false;
1185 }
1186
1187 if (length)
1188 {
1189 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1190 {
1191 const UniformBlock &uniformBlock =
1192 programObject->getUniformBlockByIndex(uniformBlockIndex);
1193 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1194 }
1195 else
1196 {
1197 *length = 1;
1198 }
1199 }
1200
1201 return true;
1202}
1203
Geoff Langebebe1c2016-10-14 12:01:31 -04001204bool ValidateGetBufferParameterBase(ValidationContext *context,
1205 GLenum target,
1206 GLenum pname,
1207 bool pointerVersion,
1208 GLsizei *numParams)
1209{
1210 if (numParams)
1211 {
1212 *numParams = 0;
1213 }
1214
1215 if (!ValidBufferTarget(context, target))
1216 {
1217 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1218 return false;
1219 }
1220
1221 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1222 if (!buffer)
1223 {
1224 // A null buffer means that "0" is bound to the requested buffer target
1225 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1226 return false;
1227 }
1228
1229 const Extensions &extensions = context->getExtensions();
1230
1231 switch (pname)
1232 {
1233 case GL_BUFFER_USAGE:
1234 case GL_BUFFER_SIZE:
1235 break;
1236
1237 case GL_BUFFER_ACCESS_OES:
1238 if (!extensions.mapBuffer)
1239 {
1240 context->handleError(
Jamie Madillcc6ac252017-01-25 12:57:21 -08001241 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001242 return false;
1243 }
1244 break;
1245
1246 case GL_BUFFER_MAPPED:
1247 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1248 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1249 !extensions.mapBufferRange)
1250 {
1251 context->handleError(Error(
1252 GL_INVALID_ENUM,
Jamie Madillcc6ac252017-01-25 12:57:21 -08001253 "pname requires OpenGL ES 3.0, GL_OES_mapbuffer or GL_EXT_map_buffer_range."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001254 return false;
1255 }
1256 break;
1257
1258 case GL_BUFFER_MAP_POINTER:
1259 if (!pointerVersion)
1260 {
1261 context->handleError(
1262 Error(GL_INVALID_ENUM,
1263 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1264 return false;
1265 }
1266 break;
1267
1268 case GL_BUFFER_ACCESS_FLAGS:
1269 case GL_BUFFER_MAP_OFFSET:
1270 case GL_BUFFER_MAP_LENGTH:
1271 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1272 {
1273 context->handleError(Error(
1274 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1275 return false;
1276 }
1277 break;
1278
1279 default:
1280 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1281 return false;
1282 }
1283
1284 // All buffer parameter queries return one value.
1285 if (numParams)
1286 {
1287 *numParams = 1;
1288 }
1289
1290 return true;
1291}
1292
Geoff Lang0a9661f2016-10-20 10:59:20 -07001293bool ValidateGetInternalFormativBase(Context *context,
1294 GLenum target,
1295 GLenum internalformat,
1296 GLenum pname,
1297 GLsizei bufSize,
1298 GLsizei *numParams)
1299{
1300 if (numParams)
1301 {
1302 *numParams = 0;
1303 }
1304
1305 if (context->getClientMajorVersion() < 3)
1306 {
1307 context->handleError(
1308 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1309 return false;
1310 }
1311
1312 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1313 if (!formatCaps.renderable)
1314 {
1315 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1316 return false;
1317 }
1318
1319 switch (target)
1320 {
1321 case GL_RENDERBUFFER:
1322 break;
1323
JiangYizhoubddc46b2016-12-09 09:50:51 +08001324 case GL_TEXTURE_2D_MULTISAMPLE:
1325 if (context->getClientVersion() < ES_3_1)
1326 {
1327 context->handleError(
1328 Error(GL_INVALID_OPERATION, "Texture target requires at least OpenGL ES 3.1."));
1329 return false;
1330 }
1331 break;
1332
Geoff Lang0a9661f2016-10-20 10:59:20 -07001333 default:
1334 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1335 return false;
1336 }
1337
1338 if (bufSize < 0)
1339 {
1340 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1341 return false;
1342 }
1343
1344 GLsizei maxWriteParams = 0;
1345 switch (pname)
1346 {
1347 case GL_NUM_SAMPLE_COUNTS:
1348 maxWriteParams = 1;
1349 break;
1350
1351 case GL_SAMPLES:
1352 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1353 break;
1354
1355 default:
1356 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1357 return false;
1358 }
1359
1360 if (numParams)
1361 {
1362 // glGetInternalFormativ will not overflow bufSize
1363 *numParams = std::min(bufSize, maxWriteParams);
1364 }
1365
1366 return true;
1367}
1368
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001369bool ValidateUniformCommonBase(gl::Context *context,
1370 gl::Program *program,
1371 GLint location,
1372 GLsizei count,
1373 const LinkedUniform **uniformOut)
1374{
1375 // TODO(Jiajia): Add image uniform check in future.
1376 if (count < 0)
1377 {
1378 context->handleError(Error(GL_INVALID_VALUE));
1379 return false;
1380 }
1381
1382 if (!program || !program->isLinked())
1383 {
1384 context->handleError(Error(GL_INVALID_OPERATION));
1385 return false;
1386 }
1387
1388 if (location == -1)
1389 {
1390 // Silently ignore the uniform command
1391 return false;
1392 }
1393
1394 const auto &uniformLocations = program->getUniformLocations();
1395 size_t castedLocation = static_cast<size_t>(location);
1396 if (castedLocation >= uniformLocations.size())
1397 {
1398 context->handleError(Error(GL_INVALID_OPERATION, "Invalid uniform location"));
1399 return false;
1400 }
1401
1402 const auto &uniformLocation = uniformLocations[castedLocation];
1403 if (uniformLocation.ignored)
1404 {
1405 // Silently ignore the uniform command
1406 return false;
1407 }
1408
1409 if (!uniformLocation.used)
1410 {
1411 context->handleError(Error(GL_INVALID_OPERATION));
1412 return false;
1413 }
1414
1415 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
1416
1417 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
1418 if (!uniform.isArray() && count > 1)
1419 {
1420 context->handleError(Error(GL_INVALID_OPERATION));
1421 return false;
1422 }
1423
1424 *uniformOut = &uniform;
1425 return true;
1426}
1427
Frank Henigman999b0fd2017-02-02 21:45:55 -05001428bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -05001429 GLenum uniformType,
1430 GLsizei count,
1431 const GLint *value)
1432{
1433 // Value type is GL_INT, because we only get here from glUniform1i{v}.
1434 // It is compatible with INT or BOOL.
1435 // Do these cheap tests first, for a little extra speed.
1436 if (GL_INT == uniformType || GL_BOOL == uniformType)
1437 {
1438 return true;
1439 }
1440
1441 if (IsSamplerType(uniformType))
1442 {
Frank Henigman999b0fd2017-02-02 21:45:55 -05001443 // Check that the values are in range.
1444 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
1445 for (GLsizei i = 0; i < count; ++i)
1446 {
1447 if (value[i] < 0 || value[i] >= max)
1448 {
1449 context->handleError(Error(GL_INVALID_VALUE, "sampler uniform value out of range"));
1450 return false;
1451 }
1452 }
Frank Henigmana98a6472017-02-02 21:38:32 -05001453 return true;
1454 }
1455
1456 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1457 return false;
1458}
1459
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001460bool ValidateUniformValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1461{
1462 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -05001463 // Do the cheaper test first, for a little extra speed.
1464 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001465 {
1466 return true;
1467 }
1468
1469 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1470 return false;
1471}
1472
1473bool ValidateUniformMatrixValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1474{
1475 // Check that the value type is compatible with uniform type.
1476 if (valueType == uniformType)
1477 {
1478 return true;
1479 }
1480
1481 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1482 return false;
1483}
1484
Geoff Langf41a7152016-09-19 15:11:17 -04001485} // anonymous namespace
1486
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001487bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001488{
Jamie Madilld7460c72014-01-21 16:38:14 -05001489 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001490 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001491 case GL_TEXTURE_2D:
1492 case GL_TEXTURE_CUBE_MAP:
1493 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001494
He Yunchaoced53ae2016-11-29 15:00:51 +08001495 case GL_TEXTURE_3D:
1496 case GL_TEXTURE_2D_ARRAY:
1497 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001498
He Yunchaoced53ae2016-11-29 15:00:51 +08001499 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001500 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001501
He Yunchaoced53ae2016-11-29 15:00:51 +08001502 default:
1503 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001504 }
Jamie Madill35d15012013-10-07 10:46:37 -04001505}
1506
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001507bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1508{
1509 switch (target)
1510 {
1511 case GL_TEXTURE_2D:
1512 case GL_TEXTURE_CUBE_MAP:
1513 return true;
1514
1515 default:
1516 return false;
1517 }
1518}
1519
1520bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1521{
1522 switch (target)
1523 {
1524 case GL_TEXTURE_3D:
1525 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001526 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001527
1528 default:
1529 return false;
1530 }
1531}
1532
Ian Ewellbda75592016-04-18 17:25:54 -04001533// Most texture GL calls are not compatible with external textures, so we have a separate validation
1534// function for use in the GL calls that do
1535bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1536{
1537 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1538 (context->getExtensions().eglImageExternal ||
1539 context->getExtensions().eglStreamConsumerExternal);
1540}
1541
Shannon Woods4dfed832014-03-17 20:03:39 -04001542// This function differs from ValidTextureTarget in that the target must be
1543// usable as the destination of a 2D operation-- so a cube face is valid, but
1544// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001545// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001546bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001547{
1548 switch (target)
1549 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001550 case GL_TEXTURE_2D:
1551 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1552 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1553 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1554 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1555 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1556 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1557 return true;
1558 default:
1559 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001560 }
1561}
1562
1563bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1564{
1565 switch (target)
1566 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001567 case GL_TEXTURE_3D:
1568 case GL_TEXTURE_2D_ARRAY:
1569 return true;
1570 default:
1571 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001572 }
1573}
1574
He Yunchao11b038b2016-11-22 21:24:04 +08001575bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1576{
1577 switch (target)
1578 {
1579 case GL_TEXTURE_2D:
1580 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1581 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1582 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1583 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1584 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1585 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1586 case GL_TEXTURE_3D:
1587 case GL_TEXTURE_2D_ARRAY:
1588 case GL_TEXTURE_2D_MULTISAMPLE:
1589 return true;
1590 default:
1591 return false;
1592 }
1593}
1594
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001595bool ValidFramebufferTarget(GLenum target)
1596{
He Yunchaoced53ae2016-11-29 15:00:51 +08001597 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1598 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001599 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001600
1601 switch (target)
1602 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001603 case GL_FRAMEBUFFER:
1604 return true;
1605 case GL_READ_FRAMEBUFFER:
1606 return true;
1607 case GL_DRAW_FRAMEBUFFER:
1608 return true;
1609 default:
1610 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001611 }
1612}
1613
Jamie Madill29639852016-09-02 15:00:09 -04001614bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001615{
1616 switch (target)
1617 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001618 case GL_ARRAY_BUFFER:
1619 case GL_ELEMENT_ARRAY_BUFFER:
1620 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001621
He Yunchaoced53ae2016-11-29 15:00:51 +08001622 case GL_PIXEL_PACK_BUFFER:
1623 case GL_PIXEL_UNPACK_BUFFER:
1624 return (context->getExtensions().pixelBufferObject ||
1625 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001626
He Yunchaoced53ae2016-11-29 15:00:51 +08001627 case GL_COPY_READ_BUFFER:
1628 case GL_COPY_WRITE_BUFFER:
1629 case GL_TRANSFORM_FEEDBACK_BUFFER:
1630 case GL_UNIFORM_BUFFER:
1631 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001632
He Yunchaoced53ae2016-11-29 15:00:51 +08001633 case GL_ATOMIC_COUNTER_BUFFER:
1634 case GL_SHADER_STORAGE_BUFFER:
1635 case GL_DRAW_INDIRECT_BUFFER:
1636 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001637 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001638
He Yunchaoced53ae2016-11-29 15:00:51 +08001639 default:
1640 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001641 }
1642}
1643
Jamie Madillc29968b2016-01-20 11:17:23 -05001644bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001645{
Jamie Madillc29968b2016-01-20 11:17:23 -05001646 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001647 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001648 switch (target)
1649 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001650 case GL_TEXTURE_2D:
1651 maxDimension = caps.max2DTextureSize;
1652 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001653 case GL_TEXTURE_CUBE_MAP:
1654 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1655 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1656 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1657 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1658 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1659 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1660 maxDimension = caps.maxCubeMapTextureSize;
1661 break;
1662 case GL_TEXTURE_3D:
1663 maxDimension = caps.max3DTextureSize;
1664 break;
1665 case GL_TEXTURE_2D_ARRAY:
1666 maxDimension = caps.max2DTextureSize;
1667 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001668 case GL_TEXTURE_2D_MULTISAMPLE:
1669 maxDimension = caps.max2DTextureSize;
1670 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001671 default:
1672 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001673 }
1674
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001675 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001676}
1677
Geoff Langcc507aa2016-12-12 10:09:52 -05001678bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001679 GLenum target,
1680 GLint level,
1681 GLsizei width,
1682 GLsizei height,
1683 GLsizei depth,
1684 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001685{
1686 if (level < 0 || width < 0 || height < 0 || depth < 0)
1687 {
1688 return false;
1689 }
1690
Austin Kinross08528e12015-10-07 16:24:40 -07001691 // TexSubImage parameters can be NPOT without textureNPOT extension,
1692 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001693 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001694 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001695 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001696 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001697 {
1698 return false;
1699 }
1700
1701 if (!ValidMipLevel(context, target, level))
1702 {
1703 return false;
1704 }
1705
1706 return true;
1707}
1708
Geoff Lang0d8b7242015-09-09 14:56:53 -04001709bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1710{
1711 // List of compressed format that require that the texture size is smaller than or a multiple of
1712 // the compressed block size.
1713 switch (internalFormat)
1714 {
1715 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1716 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1717 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1718 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001719 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001720 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1721 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1722 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1723 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1724 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
1725 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001726 return true;
1727
1728 default:
1729 return false;
1730 }
1731}
1732
Jamie Madillc29968b2016-01-20 11:17:23 -05001733bool ValidCompressedImageSize(const ValidationContext *context,
1734 GLenum internalFormat,
Geoff Lang44ff5a72017-02-03 15:15:43 -05001735 GLint xoffset,
1736 GLint yoffset,
Jamie Madillc29968b2016-01-20 11:17:23 -05001737 GLsizei width,
1738 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001739{
Geoff Lang5d601382014-07-22 15:14:06 -04001740 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1741 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001742 {
1743 return false;
1744 }
1745
Geoff Lang44ff5a72017-02-03 15:15:43 -05001746 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001747 {
1748 return false;
1749 }
1750
Geoff Lang0d8b7242015-09-09 14:56:53 -04001751 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1752 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001753 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
1754 yoffset % formatInfo.compressedBlockHeight != 0 ||
1755 (static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
Geoff Lang0d8b7242015-09-09 14:56:53 -04001756 width % formatInfo.compressedBlockWidth != 0) ||
1757 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1758 height % formatInfo.compressedBlockHeight != 0))
1759 {
1760 return false;
1761 }
1762 }
1763
Geoff Langd4f180b2013-09-24 13:57:44 -04001764 return true;
1765}
1766
Geoff Langff5b2d52016-09-07 11:32:23 -04001767bool ValidImageDataSize(ValidationContext *context,
1768 GLenum textureTarget,
1769 GLsizei width,
1770 GLsizei height,
1771 GLsizei depth,
1772 GLenum internalFormat,
1773 GLenum type,
1774 const GLvoid *pixels,
1775 GLsizei imageSize)
1776{
1777 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1778 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1779 {
1780 // Checks are not required
1781 return true;
1782 }
1783
1784 // ...the data would be unpacked from the buffer object such that the memory reads required
1785 // would exceed the data store size.
1786 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1787 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1788 const gl::Extents size(width, height, depth);
1789 const auto &unpack = context->getGLState().getUnpackState();
1790
1791 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1792 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1793 if (endByteOrErr.isError())
1794 {
1795 context->handleError(endByteOrErr.getError());
1796 return false;
1797 }
1798
1799 GLuint endByte = endByteOrErr.getResult();
1800
1801 if (pixelUnpackBuffer)
1802 {
1803 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1804 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1805 checkedEndByte += checkedOffset;
1806
1807 if (!checkedEndByte.IsValid() ||
1808 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1809 {
1810 // Overflow past the end of the buffer
1811 context->handleError(Error(GL_INVALID_OPERATION));
1812 return false;
1813 }
1814 }
1815 else
1816 {
1817 ASSERT(imageSize >= 0);
1818 if (pixels == nullptr && imageSize != 0)
1819 {
1820 context->handleError(
1821 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001822 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001823 }
1824
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001825 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001826 {
1827 context->handleError(
1828 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1829 return false;
1830 }
1831 }
1832
1833 return true;
1834}
1835
Geoff Lang37dde692014-01-31 16:34:54 -05001836bool ValidQueryType(const Context *context, GLenum queryType)
1837{
He Yunchaoced53ae2016-11-29 15:00:51 +08001838 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1839 "GL extension enums not equal.");
1840 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1841 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001842
1843 switch (queryType)
1844 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001845 case GL_ANY_SAMPLES_PASSED:
1846 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1847 return true;
1848 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1849 return (context->getClientMajorVersion() >= 3);
1850 case GL_TIME_ELAPSED_EXT:
1851 return context->getExtensions().disjointTimerQuery;
1852 case GL_COMMANDS_COMPLETED_CHROMIUM:
1853 return context->getExtensions().syncQuery;
1854 default:
1855 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001856 }
1857}
1858
Jamie Madillef300b12016-10-07 15:12:09 -04001859Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001860{
He Yunchaoced53ae2016-11-29 15:00:51 +08001861 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1862 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1863 // or program object and INVALID_OPERATION if the provided name identifies an object
1864 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001865
Dian Xiang769769a2015-09-09 15:20:08 -07001866 Program *validProgram = context->getProgram(id);
1867
1868 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001869 {
Dian Xiang769769a2015-09-09 15:20:08 -07001870 if (context->getShader(id))
1871 {
Jamie Madill437fa652016-05-03 15:13:24 -04001872 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001873 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1874 }
1875 else
1876 {
Jamie Madill437fa652016-05-03 15:13:24 -04001877 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001878 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001879 }
Dian Xiang769769a2015-09-09 15:20:08 -07001880
1881 return validProgram;
1882}
1883
Jamie Madillef300b12016-10-07 15:12:09 -04001884Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001885{
1886 // See ValidProgram for spec details.
1887
1888 Shader *validShader = context->getShader(id);
1889
1890 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001891 {
Dian Xiang769769a2015-09-09 15:20:08 -07001892 if (context->getProgram(id))
1893 {
Jamie Madill437fa652016-05-03 15:13:24 -04001894 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001895 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1896 }
1897 else
1898 {
Jamie Madill437fa652016-05-03 15:13:24 -04001899 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001900 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001901 }
Dian Xiang769769a2015-09-09 15:20:08 -07001902
1903 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001904}
1905
Geoff Langb1196682014-07-23 13:47:29 -04001906bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001907{
1908 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1909 {
1910 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1911
Geoff Langaae65a42014-05-26 12:43:44 -04001912 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001913 {
Jamie Madill437fa652016-05-03 15:13:24 -04001914 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001915 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001916 }
1917 }
1918 else
1919 {
1920 switch (attachment)
1921 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001922 case GL_DEPTH_ATTACHMENT:
1923 case GL_STENCIL_ATTACHMENT:
1924 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001925
He Yunchaoced53ae2016-11-29 15:00:51 +08001926 case GL_DEPTH_STENCIL_ATTACHMENT:
1927 if (!context->getExtensions().webglCompatibility &&
1928 context->getClientMajorVersion() < 3)
1929 {
1930 context->handleError(Error(GL_INVALID_ENUM));
1931 return false;
1932 }
1933 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001934
He Yunchaoced53ae2016-11-29 15:00:51 +08001935 default:
1936 context->handleError(Error(GL_INVALID_ENUM));
1937 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001938 }
1939 }
1940
1941 return true;
1942}
1943
Jamie Madille8fb6402017-02-14 17:56:40 -05001944bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001945 GLenum target,
1946 GLsizei samples,
1947 GLenum internalformat,
1948 GLsizei width,
1949 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001950{
1951 switch (target)
1952 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001953 case GL_RENDERBUFFER:
1954 break;
1955 default:
1956 context->handleError(Error(GL_INVALID_ENUM));
1957 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001958 }
1959
1960 if (width < 0 || height < 0 || samples < 0)
1961 {
Jamie Madill437fa652016-05-03 15:13:24 -04001962 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001963 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001964 }
1965
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001966 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1967 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1968
1969 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001970 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001971 {
Jamie Madill437fa652016-05-03 15:13:24 -04001972 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001973 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001974 }
1975
1976 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1977 // 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 -08001978 // only sized internal formats.
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001979 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(convertedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04001980 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001981 {
Jamie Madill437fa652016-05-03 15:13:24 -04001982 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001983 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001984 }
1985
Geoff Langaae65a42014-05-26 12:43:44 -04001986 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001987 {
Jamie Madill437fa652016-05-03 15:13:24 -04001988 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001989 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001990 }
1991
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001992 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001993 if (handle == 0)
1994 {
Jamie Madill437fa652016-05-03 15:13:24 -04001995 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001996 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001997 }
1998
1999 return true;
2000}
2001
He Yunchaoced53ae2016-11-29 15:00:51 +08002002bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
2003 GLenum target,
2004 GLenum attachment,
2005 GLenum renderbuffertarget,
2006 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002007{
Shannon Woods1da3cf62014-06-27 15:32:23 -04002008 if (!ValidFramebufferTarget(target))
2009 {
Jamie Madill437fa652016-05-03 15:13:24 -04002010 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002011 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04002012 }
2013
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002014 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002015
Jamie Madill84115c92015-04-23 15:00:07 -04002016 ASSERT(framebuffer);
2017 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002018 {
Jamie Madill437fa652016-05-03 15:13:24 -04002019 context->handleError(
2020 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002021 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002022 }
2023
Jamie Madillb4472272014-07-03 10:38:55 -04002024 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002025 {
Jamie Madillb4472272014-07-03 10:38:55 -04002026 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002027 }
2028
Jamie Madillab9d82c2014-01-21 16:38:14 -05002029 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2030 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2031 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2032 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2033 if (renderbuffer != 0)
2034 {
2035 if (!context->getRenderbuffer(renderbuffer))
2036 {
Jamie Madill437fa652016-05-03 15:13:24 -04002037 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002038 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05002039 }
2040 }
2041
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002042 return true;
2043}
2044
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002045bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002046 GLint srcX0,
2047 GLint srcY0,
2048 GLint srcX1,
2049 GLint srcY1,
2050 GLint dstX0,
2051 GLint dstY0,
2052 GLint dstX1,
2053 GLint dstY1,
2054 GLbitfield mask,
2055 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002056{
2057 switch (filter)
2058 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002059 case GL_NEAREST:
2060 break;
2061 case GL_LINEAR:
2062 break;
2063 default:
2064 context->handleError(Error(GL_INVALID_ENUM));
2065 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002066 }
2067
2068 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
2069 {
Jamie Madill437fa652016-05-03 15:13:24 -04002070 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002071 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002072 }
2073
2074 if (mask == 0)
2075 {
2076 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
2077 // buffers are copied.
2078 return false;
2079 }
2080
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002081 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
2082 // color buffer, leaving only nearest being unfiltered from above
2083 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
2084 {
Jamie Madill437fa652016-05-03 15:13:24 -04002085 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002086 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002087 }
2088
Jamie Madill51f40ec2016-06-15 14:06:00 -04002089 const auto &glState = context->getGLState();
2090 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2091 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05002092
2093 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002094 {
Jamie Madill437fa652016-05-03 15:13:24 -04002095 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002096 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002097 }
2098
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002099 if (readFramebuffer->id() == drawFramebuffer->id())
2100 {
2101 context->handleError(Error(GL_INVALID_OPERATION));
2102 return false;
2103 }
2104
Jamie Madill51f40ec2016-06-15 14:06:00 -04002105 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002106 {
Jamie Madill437fa652016-05-03 15:13:24 -04002107 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002108 return false;
2109 }
2110
Jamie Madill51f40ec2016-06-15 14:06:00 -04002111 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002112 {
Jamie Madill437fa652016-05-03 15:13:24 -04002113 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002114 return false;
2115 }
2116
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002117 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002118 {
Jamie Madill437fa652016-05-03 15:13:24 -04002119 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002120 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002121 }
2122
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002123 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2124
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002125 if (mask & GL_COLOR_BUFFER_BIT)
2126 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002127 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002128 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002129
He Yunchao66a41a22016-12-15 16:45:05 +08002130 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002131 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002132 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002133
Geoff Langa15472a2015-08-11 11:48:03 -04002134 for (size_t drawbufferIdx = 0;
2135 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002136 {
Geoff Langa15472a2015-08-11 11:48:03 -04002137 const FramebufferAttachment *attachment =
2138 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2139 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002140 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002141 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002142
Geoff Langb2f3d052013-08-13 12:49:27 -04002143 // The GL ES 3.0.2 spec (pg 193) states that:
2144 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002145 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2146 // as well
2147 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2148 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002149 // Changes with EXT_color_buffer_float:
2150 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002151 GLenum readComponentType = readFormat.info->componentType;
2152 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002153 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002154 readComponentType == GL_SIGNED_NORMALIZED);
2155 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2156 drawComponentType == GL_SIGNED_NORMALIZED);
2157
2158 if (extensions.colorBufferFloat)
2159 {
2160 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2161 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2162
2163 if (readFixedOrFloat != drawFixedOrFloat)
2164 {
Jamie Madill437fa652016-05-03 15:13:24 -04002165 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002166 "If the read buffer contains fixed-point or "
2167 "floating-point values, the draw buffer "
2168 "must as well."));
2169 return false;
2170 }
2171 }
2172 else if (readFixedPoint != drawFixedPoint)
2173 {
Jamie Madill437fa652016-05-03 15:13:24 -04002174 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002175 "If the read buffer contains fixed-point "
2176 "values, the draw buffer must as well."));
2177 return false;
2178 }
2179
2180 if (readComponentType == GL_UNSIGNED_INT &&
2181 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002182 {
Jamie Madill437fa652016-05-03 15:13:24 -04002183 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002184 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002185 }
2186
Jamie Madill6163c752015-12-07 16:32:59 -05002187 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002188 {
Jamie Madill437fa652016-05-03 15:13:24 -04002189 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002190 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002191 }
2192
Jamie Madilla3944d42016-07-22 22:13:26 -04002193 if (readColorBuffer->getSamples() > 0 &&
2194 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002195 {
Jamie Madill437fa652016-05-03 15:13:24 -04002196 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002197 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002198 }
2199 }
2200 }
2201
Jamie Madilla3944d42016-07-22 22:13:26 -04002202 if ((readFormat.info->componentType == GL_INT ||
2203 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2204 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002205 {
Jamie Madill437fa652016-05-03 15:13:24 -04002206 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002207 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002208 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002209 }
He Yunchao66a41a22016-12-15 16:45:05 +08002210 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2211 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2212 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2213 // situation is an application error that would lead to a crash in ANGLE.
2214 else if (drawFramebuffer->hasEnabledDrawBuffer())
2215 {
2216 context->handleError(Error(
2217 GL_INVALID_OPERATION,
2218 "Attempt to read from a missing color attachment of a complete framebuffer."));
2219 return false;
2220 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002221 }
2222
He Yunchaoced53ae2016-11-29 15:00:51 +08002223 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002224 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2225 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002226 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002227 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002228 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002229 const gl::FramebufferAttachment *readBuffer =
2230 readFramebuffer->getAttachment(attachments[i]);
2231 const gl::FramebufferAttachment *drawBuffer =
2232 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002233
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002234 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002235 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002236 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002237 {
Jamie Madill437fa652016-05-03 15:13:24 -04002238 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002239 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002240 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002241
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002242 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002243 {
Jamie Madill437fa652016-05-03 15:13:24 -04002244 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002245 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002246 }
2247 }
He Yunchao66a41a22016-12-15 16:45:05 +08002248 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2249 else if (drawBuffer)
2250 {
2251 context->handleError(Error(GL_INVALID_OPERATION,
2252 "Attempt to read from a missing depth/stencil "
2253 "attachment of a complete framebuffer."));
2254 return false;
2255 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002256 }
2257 }
2258
2259 return true;
2260}
2261
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002262bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002263 GLint x,
2264 GLint y,
2265 GLsizei width,
2266 GLsizei height,
2267 GLenum format,
2268 GLenum type,
2269 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002270{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002271 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2272}
2273
2274bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2275 GLint x,
2276 GLint y,
2277 GLsizei width,
2278 GLsizei height,
2279 GLenum format,
2280 GLenum type,
2281 GLsizei bufSize,
2282 GLsizei *length,
2283 GLvoid *pixels)
2284{
2285 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002286 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002287 return false;
2288 }
2289
Geoff Lang62fce5b2016-09-30 10:46:35 -04002290 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2291 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002292 {
Geoff Langb1196682014-07-23 13:47:29 -04002293 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002294 }
2295
Geoff Lang62fce5b2016-09-30 10:46:35 -04002296 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002297 {
Geoff Langb1196682014-07-23 13:47:29 -04002298 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002299 }
2300
Jamie Madillc29968b2016-01-20 11:17:23 -05002301 return true;
2302}
2303
2304bool ValidateReadnPixelsEXT(Context *context,
2305 GLint x,
2306 GLint y,
2307 GLsizei width,
2308 GLsizei height,
2309 GLenum format,
2310 GLenum type,
2311 GLsizei bufSize,
2312 GLvoid *pixels)
2313{
2314 if (bufSize < 0)
2315 {
Jamie Madill437fa652016-05-03 15:13:24 -04002316 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002317 return false;
2318 }
2319
Geoff Lang62fce5b2016-09-30 10:46:35 -04002320 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2321 pixels);
2322}
Jamie Madill26e91952014-03-05 15:01:27 -05002323
Geoff Lang62fce5b2016-09-30 10:46:35 -04002324bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2325 GLint x,
2326 GLint y,
2327 GLsizei width,
2328 GLsizei height,
2329 GLenum format,
2330 GLenum type,
2331 GLsizei bufSize,
2332 GLsizei *length,
2333 GLvoid *data)
2334{
2335 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002336 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002337 return false;
2338 }
2339
Geoff Lang62fce5b2016-09-30 10:46:35 -04002340 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002341 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002342 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002343 }
2344
Geoff Lang62fce5b2016-09-30 10:46:35 -04002345 if (!ValidateRobustBufferSize(context, bufSize, *length))
2346 {
2347 return false;
2348 }
2349
2350 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002351}
2352
Olli Etuaho41997e72016-03-10 13:38:39 +02002353bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002354{
2355 if (!context->getExtensions().occlusionQueryBoolean &&
2356 !context->getExtensions().disjointTimerQuery)
2357 {
Jamie Madill437fa652016-05-03 15:13:24 -04002358 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002359 return false;
2360 }
2361
Olli Etuaho41997e72016-03-10 13:38:39 +02002362 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002363}
2364
Olli Etuaho41997e72016-03-10 13:38:39 +02002365bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002366{
2367 if (!context->getExtensions().occlusionQueryBoolean &&
2368 !context->getExtensions().disjointTimerQuery)
2369 {
Jamie Madill437fa652016-05-03 15:13:24 -04002370 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002371 return false;
2372 }
2373
Olli Etuaho41997e72016-03-10 13:38:39 +02002374 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002375}
2376
2377bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002378{
2379 if (!ValidQueryType(context, target))
2380 {
Jamie Madill437fa652016-05-03 15:13:24 -04002381 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002382 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002383 }
2384
2385 if (id == 0)
2386 {
Jamie Madill437fa652016-05-03 15:13:24 -04002387 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002388 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002389 }
2390
2391 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2392 // of zero, if the active query object name for <target> is non-zero (for the
2393 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2394 // the active query for either target is non-zero), if <id> is the name of an
2395 // existing query object whose type does not match <target>, or if <id> is the
2396 // active query object name for any query type, the error INVALID_OPERATION is
2397 // generated.
2398
2399 // Ensure no other queries are active
2400 // NOTE: If other queries than occlusion are supported, we will need to check
2401 // separately that:
2402 // a) The query ID passed is not the current active query for any target/type
2403 // b) There are no active queries for the requested target (and in the case
2404 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2405 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002406
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002407 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002408 {
Jamie Madill437fa652016-05-03 15:13:24 -04002409 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002410 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002411 }
2412
2413 Query *queryObject = context->getQuery(id, true, target);
2414
2415 // check that name was obtained with glGenQueries
2416 if (!queryObject)
2417 {
Jamie Madill437fa652016-05-03 15:13:24 -04002418 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002419 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002420 }
2421
2422 // check for type mismatch
2423 if (queryObject->getType() != target)
2424 {
Jamie Madill437fa652016-05-03 15:13:24 -04002425 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002426 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002427 }
2428
2429 return true;
2430}
2431
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002432bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2433{
2434 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002435 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002436 {
Jamie Madill437fa652016-05-03 15:13:24 -04002437 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002438 return false;
2439 }
2440
2441 return ValidateBeginQueryBase(context, target, id);
2442}
2443
2444bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002445{
2446 if (!ValidQueryType(context, target))
2447 {
Jamie Madill437fa652016-05-03 15:13:24 -04002448 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002449 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002450 }
2451
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002452 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002453
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002454 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002455 {
Jamie Madill437fa652016-05-03 15:13:24 -04002456 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002457 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002458 }
2459
Jamie Madill45c785d2014-05-13 14:09:34 -04002460 return true;
2461}
2462
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002463bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2464{
2465 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002466 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002467 {
Jamie Madill437fa652016-05-03 15:13:24 -04002468 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002469 return false;
2470 }
2471
2472 return ValidateEndQueryBase(context, target);
2473}
2474
2475bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2476{
2477 if (!context->getExtensions().disjointTimerQuery)
2478 {
Jamie Madill437fa652016-05-03 15:13:24 -04002479 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002480 return false;
2481 }
2482
2483 if (target != GL_TIMESTAMP_EXT)
2484 {
Jamie Madill437fa652016-05-03 15:13:24 -04002485 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002486 return false;
2487 }
2488
2489 Query *queryObject = context->getQuery(id, true, target);
2490 if (queryObject == nullptr)
2491 {
Jamie Madill437fa652016-05-03 15:13:24 -04002492 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002493 return false;
2494 }
2495
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002496 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002497 {
Jamie Madill437fa652016-05-03 15:13:24 -04002498 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002499 return false;
2500 }
2501
2502 return true;
2503}
2504
Geoff Lang2186c382016-10-14 10:54:54 -04002505bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002506{
Geoff Lang2186c382016-10-14 10:54:54 -04002507 if (numParams)
2508 {
2509 *numParams = 0;
2510 }
2511
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002512 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2513 {
Jamie Madill437fa652016-05-03 15:13:24 -04002514 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002515 return false;
2516 }
2517
2518 switch (pname)
2519 {
2520 case GL_CURRENT_QUERY_EXT:
2521 if (target == GL_TIMESTAMP_EXT)
2522 {
Jamie Madill437fa652016-05-03 15:13:24 -04002523 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002524 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2525 return false;
2526 }
2527 break;
2528 case GL_QUERY_COUNTER_BITS_EXT:
2529 if (!context->getExtensions().disjointTimerQuery ||
2530 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2531 {
Jamie Madill437fa652016-05-03 15:13:24 -04002532 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002533 return false;
2534 }
2535 break;
2536 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002537 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002538 return false;
2539 }
2540
Geoff Lang2186c382016-10-14 10:54:54 -04002541 if (numParams)
2542 {
2543 // All queries return only one value
2544 *numParams = 1;
2545 }
2546
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002547 return true;
2548}
2549
2550bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2551{
2552 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002553 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002554 {
Jamie Madill437fa652016-05-03 15:13:24 -04002555 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002556 return false;
2557 }
2558
Geoff Lang2186c382016-10-14 10:54:54 -04002559 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002560}
2561
Geoff Lang2186c382016-10-14 10:54:54 -04002562bool ValidateGetQueryivRobustANGLE(Context *context,
2563 GLenum target,
2564 GLenum pname,
2565 GLsizei bufSize,
2566 GLsizei *length,
2567 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002568{
Geoff Lang2186c382016-10-14 10:54:54 -04002569 if (!ValidateRobustEntryPoint(context, bufSize))
2570 {
2571 return false;
2572 }
2573
2574 if (!ValidateGetQueryivBase(context, target, pname, length))
2575 {
2576 return false;
2577 }
2578
2579 if (!ValidateRobustBufferSize(context, bufSize, *length))
2580 {
2581 return false;
2582 }
2583
2584 return true;
2585}
2586
2587bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2588{
2589 if (numParams)
2590 {
2591 *numParams = 0;
2592 }
2593
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002594 Query *queryObject = context->getQuery(id, false, GL_NONE);
2595
2596 if (!queryObject)
2597 {
Jamie Madill437fa652016-05-03 15:13:24 -04002598 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002599 return false;
2600 }
2601
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002602 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002603 {
Jamie Madill437fa652016-05-03 15:13:24 -04002604 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002605 return false;
2606 }
2607
2608 switch (pname)
2609 {
2610 case GL_QUERY_RESULT_EXT:
2611 case GL_QUERY_RESULT_AVAILABLE_EXT:
2612 break;
2613
2614 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002615 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002616 return false;
2617 }
2618
Geoff Lang2186c382016-10-14 10:54:54 -04002619 if (numParams)
2620 {
2621 *numParams = 1;
2622 }
2623
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002624 return true;
2625}
2626
2627bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2628{
2629 if (!context->getExtensions().disjointTimerQuery)
2630 {
Jamie Madill437fa652016-05-03 15:13:24 -04002631 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002632 return false;
2633 }
Geoff Lang2186c382016-10-14 10:54:54 -04002634 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2635}
2636
2637bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2638 GLuint id,
2639 GLenum pname,
2640 GLsizei bufSize,
2641 GLsizei *length,
2642 GLint *params)
2643{
2644 if (!context->getExtensions().disjointTimerQuery)
2645 {
2646 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2647 return false;
2648 }
2649
2650 if (!ValidateRobustEntryPoint(context, bufSize))
2651 {
2652 return false;
2653 }
2654
2655 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2656 {
2657 return false;
2658 }
2659
2660 if (!ValidateRobustBufferSize(context, bufSize, *length))
2661 {
2662 return false;
2663 }
2664
2665 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002666}
2667
2668bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2669{
2670 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002671 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002672 {
Jamie Madill437fa652016-05-03 15:13:24 -04002673 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002674 return false;
2675 }
Geoff Lang2186c382016-10-14 10:54:54 -04002676 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2677}
2678
2679bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2680 GLuint id,
2681 GLenum pname,
2682 GLsizei bufSize,
2683 GLsizei *length,
2684 GLuint *params)
2685{
2686 if (!context->getExtensions().disjointTimerQuery &&
2687 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2688 {
2689 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2690 return false;
2691 }
2692
2693 if (!ValidateRobustEntryPoint(context, bufSize))
2694 {
2695 return false;
2696 }
2697
2698 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2699 {
2700 return false;
2701 }
2702
2703 if (!ValidateRobustBufferSize(context, bufSize, *length))
2704 {
2705 return false;
2706 }
2707
2708 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002709}
2710
2711bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2712{
2713 if (!context->getExtensions().disjointTimerQuery)
2714 {
Jamie Madill437fa652016-05-03 15:13:24 -04002715 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002716 return false;
2717 }
Geoff Lang2186c382016-10-14 10:54:54 -04002718 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2719}
2720
2721bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2722 GLuint id,
2723 GLenum pname,
2724 GLsizei bufSize,
2725 GLsizei *length,
2726 GLint64 *params)
2727{
2728 if (!context->getExtensions().disjointTimerQuery)
2729 {
2730 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2731 return false;
2732 }
2733
2734 if (!ValidateRobustEntryPoint(context, bufSize))
2735 {
2736 return false;
2737 }
2738
2739 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2740 {
2741 return false;
2742 }
2743
2744 if (!ValidateRobustBufferSize(context, bufSize, *length))
2745 {
2746 return false;
2747 }
2748
2749 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002750}
2751
2752bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2753{
2754 if (!context->getExtensions().disjointTimerQuery)
2755 {
Jamie Madill437fa652016-05-03 15:13:24 -04002756 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002757 return false;
2758 }
Geoff Lang2186c382016-10-14 10:54:54 -04002759 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2760}
2761
2762bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2763 GLuint id,
2764 GLenum pname,
2765 GLsizei bufSize,
2766 GLsizei *length,
2767 GLuint64 *params)
2768{
2769 if (!context->getExtensions().disjointTimerQuery)
2770 {
2771 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2772 return false;
2773 }
2774
2775 if (!ValidateRobustEntryPoint(context, bufSize))
2776 {
2777 return false;
2778 }
2779
2780 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2781 {
2782 return false;
2783 }
2784
2785 if (!ValidateRobustBufferSize(context, bufSize, *length))
2786 {
2787 return false;
2788 }
2789
2790 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002791}
2792
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002793bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002794 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002795 GLuint program,
2796 GLint location,
2797 GLsizei count)
2798{
2799 // Check for ES31 program uniform entry points
2800 if (context->getClientVersion() < Version(3, 1))
2801 {
2802 context->handleError(Error(GL_INVALID_OPERATION));
2803 return false;
2804 }
2805
2806 const LinkedUniform *uniform = nullptr;
2807 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002808 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2809 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002810}
2811
Frank Henigmana98a6472017-02-02 21:38:32 -05002812bool ValidateProgramUniform1iv(gl::Context *context,
2813 GLuint program,
2814 GLint location,
2815 GLsizei count,
2816 const GLint *value)
2817{
2818 // Check for ES31 program uniform entry points
2819 if (context->getClientVersion() < Version(3, 1))
2820 {
2821 context->handleError(Error(GL_INVALID_OPERATION));
2822 return false;
2823 }
2824
2825 const LinkedUniform *uniform = nullptr;
2826 gl::Program *programObject = GetValidProgram(context, program);
2827 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2828 ValidateUniform1ivValue(context, uniform->type, count, value);
2829}
2830
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002831bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002832 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002833 GLuint program,
2834 GLint location,
2835 GLsizei count,
2836 GLboolean transpose)
2837{
2838 // Check for ES31 program uniform entry points
2839 if (context->getClientVersion() < Version(3, 1))
2840 {
2841 context->handleError(Error(GL_INVALID_OPERATION));
2842 return false;
2843 }
2844
2845 const LinkedUniform *uniform = nullptr;
2846 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002847 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2848 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002849}
2850
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002851bool ValidateUniform(gl::Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002852{
2853 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002854 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002855 {
Jamie Madill437fa652016-05-03 15:13:24 -04002856 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002857 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002858 }
2859
Jamie Madill62d31cb2015-09-11 13:25:51 -04002860 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002861 gl::Program *programObject = context->getGLState().getProgram();
2862 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2863 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002864}
2865
Frank Henigmana98a6472017-02-02 21:38:32 -05002866bool ValidateUniform1iv(gl::Context *context, GLint location, GLsizei count, const GLint *value)
2867{
2868 const LinkedUniform *uniform = nullptr;
2869 gl::Program *programObject = context->getGLState().getProgram();
2870 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2871 ValidateUniform1ivValue(context, uniform->type, count, value);
2872}
2873
He Yunchaoced53ae2016-11-29 15:00:51 +08002874bool ValidateUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002875 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002876 GLint location,
2877 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002878 GLboolean transpose)
2879{
2880 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002881 int rows = VariableRowCount(valueType);
2882 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002883 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002884 {
Jamie Madill437fa652016-05-03 15:13:24 -04002885 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002886 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002887 }
2888
Martin Radev1be913c2016-07-11 17:59:16 +03002889 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002890 {
Jamie Madill437fa652016-05-03 15:13:24 -04002891 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002892 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002893 }
2894
Jamie Madill62d31cb2015-09-11 13:25:51 -04002895 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002896 gl::Program *programObject = context->getGLState().getProgram();
2897 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2898 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002899}
2900
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002901bool ValidateStateQuery(ValidationContext *context,
2902 GLenum pname,
2903 GLenum *nativeType,
2904 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002905{
2906 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2907 {
Jamie Madill437fa652016-05-03 15:13:24 -04002908 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002909 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002910 }
2911
Jamie Madill0af26e12015-03-05 19:54:33 -05002912 const Caps &caps = context->getCaps();
2913
Jamie Madill893ab082014-05-16 16:56:10 -04002914 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2915 {
2916 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2917
Jamie Madill0af26e12015-03-05 19:54:33 -05002918 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002919 {
Jamie Madill437fa652016-05-03 15:13:24 -04002920 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002921 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002922 }
2923 }
2924
2925 switch (pname)
2926 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002927 case GL_TEXTURE_BINDING_2D:
2928 case GL_TEXTURE_BINDING_CUBE_MAP:
2929 case GL_TEXTURE_BINDING_3D:
2930 case GL_TEXTURE_BINDING_2D_ARRAY:
2931 break;
2932 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2933 if (!context->getExtensions().eglStreamConsumerExternal &&
2934 !context->getExtensions().eglImageExternal)
2935 {
2936 context->handleError(Error(GL_INVALID_ENUM,
2937 "Neither NV_EGL_stream_consumer_external nor "
2938 "GL_OES_EGL_image_external extensions enabled"));
2939 return false;
2940 }
2941 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002942
He Yunchaoced53ae2016-11-29 15:00:51 +08002943 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2944 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002945 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002946 if (context->getGLState().getReadFramebuffer()->checkStatus(
2947 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002948 {
Jamie Madill437fa652016-05-03 15:13:24 -04002949 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002950 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002951 }
2952
Jamie Madill51f40ec2016-06-15 14:06:00 -04002953 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2954 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002955
2956 if (framebuffer->getReadBufferState() == GL_NONE)
2957 {
2958 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2959 return false;
2960 }
2961
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002962 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002963 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002964 {
Jamie Madill437fa652016-05-03 15:13:24 -04002965 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002966 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002967 }
2968 }
2969 break;
2970
He Yunchaoced53ae2016-11-29 15:00:51 +08002971 default:
2972 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002973 }
2974
2975 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002976 if (*numParams == 0)
2977 {
2978 return false;
2979 }
2980
2981 return true;
2982}
2983
2984bool ValidateRobustStateQuery(ValidationContext *context,
2985 GLenum pname,
2986 GLsizei bufSize,
2987 GLenum *nativeType,
2988 unsigned int *numParams)
2989{
2990 if (!ValidateRobustEntryPoint(context, bufSize))
2991 {
2992 return false;
2993 }
2994
2995 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2996 {
2997 return false;
2998 }
2999
3000 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04003001 {
3002 return false;
3003 }
3004
3005 return true;
3006}
3007
Jamie Madillc29968b2016-01-20 11:17:23 -05003008bool ValidateCopyTexImageParametersBase(ValidationContext *context,
3009 GLenum target,
3010 GLint level,
3011 GLenum internalformat,
3012 bool isSubImage,
3013 GLint xoffset,
3014 GLint yoffset,
3015 GLint zoffset,
3016 GLint x,
3017 GLint y,
3018 GLsizei width,
3019 GLsizei height,
3020 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04003021 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04003022{
Jamie Madill560a8d82014-05-21 13:06:20 -04003023 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
3024 {
Jamie Madill437fa652016-05-03 15:13:24 -04003025 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003026 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003027 }
3028
He Yunchaoced53ae2016-11-29 15:00:51 +08003029 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3030 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04003031 {
Jamie Madill437fa652016-05-03 15:13:24 -04003032 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003033 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003034 }
3035
3036 if (border != 0)
3037 {
Jamie Madill437fa652016-05-03 15:13:24 -04003038 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003039 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003040 }
3041
3042 if (!ValidMipLevel(context, target, level))
3043 {
Jamie Madill437fa652016-05-03 15:13:24 -04003044 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003045 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003046 }
3047
Jamie Madill51f40ec2016-06-15 14:06:00 -04003048 const auto &state = context->getGLState();
3049 auto readFramebuffer = state.getReadFramebuffer();
3050 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003051 {
Jamie Madill437fa652016-05-03 15:13:24 -04003052 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003053 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003054 }
3055
Jamie Madill51f40ec2016-06-15 14:06:00 -04003056 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003057 {
Jamie Madill437fa652016-05-03 15:13:24 -04003058 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003059 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003060 }
3061
Martin Radev138064f2016-07-15 12:03:41 +03003062 if (readFramebuffer->getReadBufferState() == GL_NONE)
3063 {
3064 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3065 return false;
3066 }
3067
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003068 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3069 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003070 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003071 // situation is an application error that would lead to a crash in ANGLE.
3072 if (readFramebuffer->getReadColorbuffer() == nullptr)
3073 {
3074 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3075 return false;
3076 }
3077
Geoff Langaae65a42014-05-26 12:43:44 -04003078 const gl::Caps &caps = context->getCaps();
3079
Geoff Langaae65a42014-05-26 12:43:44 -04003080 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003081 switch (target)
3082 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003083 case GL_TEXTURE_2D:
3084 maxDimension = caps.max2DTextureSize;
3085 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003086
He Yunchaoced53ae2016-11-29 15:00:51 +08003087 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3088 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3089 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3090 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3091 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3092 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3093 maxDimension = caps.maxCubeMapTextureSize;
3094 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003095
He Yunchaoced53ae2016-11-29 15:00:51 +08003096 case GL_TEXTURE_2D_ARRAY:
3097 maxDimension = caps.max2DTextureSize;
3098 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003099
He Yunchaoced53ae2016-11-29 15:00:51 +08003100 case GL_TEXTURE_3D:
3101 maxDimension = caps.max3DTextureSize;
3102 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003103
He Yunchaoced53ae2016-11-29 15:00:51 +08003104 default:
3105 context->handleError(Error(GL_INVALID_ENUM));
3106 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003107 }
3108
Jamie Madillc29968b2016-01-20 11:17:23 -05003109 gl::Texture *texture =
3110 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003111 if (!texture)
3112 {
Jamie Madill437fa652016-05-03 15:13:24 -04003113 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003114 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003115 }
3116
Geoff Lang69cce582015-09-17 13:20:36 -04003117 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003118 {
Jamie Madill437fa652016-05-03 15:13:24 -04003119 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003120 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003121 }
3122
Geoff Lang5d601382014-07-22 15:14:06 -04003123 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3124
3125 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003126 {
Jamie Madill437fa652016-05-03 15:13:24 -04003127 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003128 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003129 }
3130
Geoff Lang44ff5a72017-02-03 15:15:43 -05003131 if (formatInfo.compressed &&
3132 !ValidCompressedImageSize(context, internalformat, xoffset, yoffset, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003133 {
Jamie Madill437fa652016-05-03 15:13:24 -04003134 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003135 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003136 }
3137
3138 if (isSubImage)
3139 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003140 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3141 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3142 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003143 {
Jamie Madill437fa652016-05-03 15:13:24 -04003144 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003145 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003146 }
3147 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003148 else
3149 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003150 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003151 {
Jamie Madill437fa652016-05-03 15:13:24 -04003152 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003153 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003154 }
3155
Geoff Langeb66a6e2016-10-31 13:06:12 -04003156 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003157 {
Jamie Madill437fa652016-05-03 15:13:24 -04003158 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003159 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003160 }
3161
3162 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003163 if (static_cast<int>(width) > maxLevelDimension ||
3164 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003165 {
Jamie Madill437fa652016-05-03 15:13:24 -04003166 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003167 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003168 }
3169 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003170
Jamie Madill0c8abca2016-07-22 20:21:26 -04003171 if (textureFormatOut)
3172 {
3173 *textureFormatOut = texture->getFormat(target, level);
3174 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003175
3176 // Detect texture copying feedback loops for WebGL.
3177 if (context->getExtensions().webglCompatibility)
3178 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05003179 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05003180 {
3181 context->handleError(Error(GL_INVALID_OPERATION,
3182 "Texture copying feedback loop formed between Framebuffer "
3183 "and specified Texture level."));
3184 return false;
3185 }
3186 }
3187
Jamie Madill560a8d82014-05-21 13:06:20 -04003188 return true;
3189}
3190
Jiajia Qind9671222016-11-29 16:30:31 +08003191bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003192{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003193 switch (mode)
3194 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003195 case GL_POINTS:
3196 case GL_LINES:
3197 case GL_LINE_LOOP:
3198 case GL_LINE_STRIP:
3199 case GL_TRIANGLES:
3200 case GL_TRIANGLE_STRIP:
3201 case GL_TRIANGLE_FAN:
3202 break;
3203 default:
3204 context->handleError(Error(GL_INVALID_ENUM));
3205 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003206 }
3207
Jamie Madill250d33f2014-06-06 17:09:03 -04003208 if (count < 0)
3209 {
Jamie Madill437fa652016-05-03 15:13:24 -04003210 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003211 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003212 }
3213
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003214 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003215
Jamie Madill250d33f2014-06-06 17:09:03 -04003216 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003217 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003218 {
Jamie Madill437fa652016-05-03 15:13:24 -04003219 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003220 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003221 }
3222
Jamie Madillcbcde722017-01-06 14:50:00 -05003223 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3224 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003225 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003226 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3227 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003228 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003229 const FramebufferAttachment *dsAttachment =
3230 framebuffer->getStencilOrDepthStencilAttachment();
3231 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003232 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003233 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003234
3235 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3236 bool differentWritemasks =
3237 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3238 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3239 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3240 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3241
3242 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003243 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003244 if (!context->getExtensions().webglCompatibility)
3245 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003246 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3247 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003248 }
Jamie Madill437fa652016-05-03 15:13:24 -04003249 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003250 return false;
3251 }
Jamie Madillac528012014-06-20 13:21:23 -04003252 }
3253
Jamie Madill51f40ec2016-06-15 14:06:00 -04003254 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003255 {
Jamie Madill437fa652016-05-03 15:13:24 -04003256 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003257 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003258 }
3259
Geoff Lang7dd2e102014-11-10 15:19:26 -05003260 gl::Program *program = state.getProgram();
3261 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003262 {
Jamie Madill437fa652016-05-03 15:13:24 -04003263 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003264 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003265 }
3266
Geoff Lang7dd2e102014-11-10 15:19:26 -05003267 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003268 {
Jamie Madill437fa652016-05-03 15:13:24 -04003269 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003270 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003271 }
3272
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003273 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003274 for (unsigned int uniformBlockIndex = 0;
3275 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003276 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003277 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003278 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003279 const OffsetBindingPointer<Buffer> &uniformBuffer =
3280 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003281
Geoff Lang5d124a62015-09-15 13:03:27 -04003282 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003283 {
3284 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003285 context->handleError(
3286 Error(GL_INVALID_OPERATION,
3287 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003288 return false;
3289 }
3290
Geoff Lang5d124a62015-09-15 13:03:27 -04003291 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003292 if (uniformBufferSize == 0)
3293 {
3294 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003295 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003296 }
3297
Jamie Madill62d31cb2015-09-11 13:25:51 -04003298 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003299 {
3300 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003301 context->handleError(
3302 Error(GL_INVALID_OPERATION,
3303 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003304 return false;
3305 }
3306 }
3307
Jamie Madilla4595b82017-01-11 17:36:34 -05003308 // Detect rendering feedback loops for WebGL.
3309 if (context->getExtensions().webglCompatibility)
3310 {
3311 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3312 {
3313 context->handleError(
3314 Error(GL_INVALID_OPERATION,
3315 "Rendering feedback loop formed between Framebuffer and active Texture."));
3316 return false;
3317 }
3318 }
3319
Jamie Madill250d33f2014-06-06 17:09:03 -04003320 // No-op if zero count
3321 return (count > 0);
3322}
3323
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003324bool ValidateDrawArrays(ValidationContext *context,
3325 GLenum mode,
3326 GLint first,
3327 GLsizei count,
3328 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003329{
Jamie Madillfd716582014-06-06 17:09:04 -04003330 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003331 {
Jamie Madill437fa652016-05-03 15:13:24 -04003332 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003333 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003334 }
3335
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003336 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003337 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003338 if (curTransformFeedback && curTransformFeedback->isActive() &&
3339 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003340 {
3341 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003342 // that does not match the current transform feedback object's draw mode (if transform
3343 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003344 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003345 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003346 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003347 }
3348
Jiajia Qind9671222016-11-29 16:30:31 +08003349 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003350 {
3351 return false;
3352 }
3353
Corentin Wallez71168a02016-12-19 15:11:18 -08003354 // Check the computation of maxVertex doesn't overflow.
3355 // - first < 0 or count < 0 have been checked as an error condition
3356 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3357 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3358 ASSERT(count > 0 && first >= 0);
3359 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3360 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003361 {
3362 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3363 return false;
3364 }
3365
Corentin Wallez71168a02016-12-19 15:11:18 -08003366 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003367 {
3368 return false;
3369 }
3370
3371 return true;
3372}
3373
He Yunchaoced53ae2016-11-29 15:00:51 +08003374bool ValidateDrawArraysInstanced(Context *context,
3375 GLenum mode,
3376 GLint first,
3377 GLsizei count,
3378 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003379{
3380 if (primcount < 0)
3381 {
Jamie Madill437fa652016-05-03 15:13:24 -04003382 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003383 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003384 }
3385
Jamie Madill2b976812014-08-25 15:47:49 -04003386 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003387 {
3388 return false;
3389 }
3390
3391 // No-op if zero primitive count
3392 return (primcount > 0);
3393}
3394
Geoff Lang87a93302014-09-16 13:29:43 -04003395static bool ValidateDrawInstancedANGLE(Context *context)
3396{
3397 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003398 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003399
Geoff Lang7dd2e102014-11-10 15:19:26 -05003400 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003401
Jiawei-Shao2597fb62016-12-09 16:38:02 +08003402 const auto &attribs = state.getVertexArray()->getVertexAttributes();
3403 const auto &bindings = state.getVertexArray()->getVertexBindings();
Jamie Madill63805b42015-08-25 13:17:39 -04003404 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003405 {
Jiawei-Shao2597fb62016-12-09 16:38:02 +08003406 const VertexAttribute &attrib = attribs[attributeIndex];
3407 const VertexBinding &binding = bindings[attrib.bindingIndex];
3408 if (program->isAttribLocationActive(attributeIndex) && binding.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003409 {
3410 return true;
3411 }
3412 }
3413
Jamie Madill437fa652016-05-03 15:13:24 -04003414 context->handleError(Error(GL_INVALID_OPERATION,
3415 "ANGLE_instanced_arrays requires that at least one active attribute"
3416 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003417 return false;
3418}
3419
He Yunchaoced53ae2016-11-29 15:00:51 +08003420bool ValidateDrawArraysInstancedANGLE(Context *context,
3421 GLenum mode,
3422 GLint first,
3423 GLsizei count,
3424 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003425{
3426 if (!ValidateDrawInstancedANGLE(context))
3427 {
3428 return false;
3429 }
3430
3431 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3432}
3433
Jiajia Qind9671222016-11-29 16:30:31 +08003434bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003435{
Jamie Madill250d33f2014-06-06 17:09:03 -04003436 switch (type)
3437 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003438 case GL_UNSIGNED_BYTE:
3439 case GL_UNSIGNED_SHORT:
3440 break;
3441 case GL_UNSIGNED_INT:
3442 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3443 {
3444 context->handleError(Error(GL_INVALID_ENUM));
3445 return false;
3446 }
3447 break;
3448 default:
3449 context->handleError(Error(GL_INVALID_ENUM));
3450 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003451 }
3452
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003453 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003454
3455 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003456 if (curTransformFeedback && curTransformFeedback->isActive() &&
3457 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003458 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003459 // It is an invalid operation to call DrawElements, DrawRangeElements or
3460 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003461 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003462 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003463 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003464 }
3465
Jiajia Qind9671222016-11-29 16:30:31 +08003466 return true;
3467}
3468
3469bool ValidateDrawElements(ValidationContext *context,
3470 GLenum mode,
3471 GLsizei count,
3472 GLenum type,
3473 const GLvoid *indices,
3474 GLsizei primcount,
3475 IndexRange *indexRangeOut)
3476{
3477 if (!ValidateDrawElementsBase(context, type))
3478 return false;
3479
3480 const State &state = context->getGLState();
3481
Jamie Madill250d33f2014-06-06 17:09:03 -04003482 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003483 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003484 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003485 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04003486 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003487 }
3488
He Yunchaoced53ae2016-11-29 15:00:51 +08003489 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003490 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003491
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003492 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3493
3494 if (context->getExtensions().webglCompatibility)
3495 {
3496 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3497 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3498 {
3499 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3500 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3501 // data type passed to the call, or an INVALID_OPERATION error is generated.
3502 context->handleError(Error(GL_INVALID_OPERATION,
3503 "indices must be a multiple of the element type size."));
3504 return false;
3505 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003506
3507 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3508 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3509 // error is generated.
3510 if (reinterpret_cast<intptr_t>(indices) < 0)
3511 {
3512 context->handleError(Error(GL_INVALID_VALUE, "Offset < 0."));
3513 return false;
3514 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003515 }
3516
3517 if (context->getExtensions().webglCompatibility ||
3518 !context->getGLState().areClientArraysEnabled())
3519 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003520 if (!elementArrayBuffer && count > 0)
3521 {
3522 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3523 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3524 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3525 context->handleError(Error(GL_INVALID_OPERATION,
3526 "There is no element array buffer bound and count > 0."));
3527 return false;
3528 }
3529 }
3530
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003531 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003532 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003533 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003534 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003535 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3536 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3537 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3538 constexpr uint64_t kMaxTypeSize = 8;
3539 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3540 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3541 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003542
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003543 uint64_t typeSize = typeBytes;
3544 uint64_t elementCount = static_cast<uint64_t>(count);
3545 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3546
3547 // Doing the multiplication here is overflow-safe
3548 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3549
3550 // The offset can be any value, check for overflows
3551 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3552 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003553 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003554 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003555 return false;
3556 }
3557
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003558 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3559 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003560 {
3561 context->handleError(
3562 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
3563 return false;
3564 }
3565 }
3566 else if (!indices)
3567 {
3568 // This is an application error that would normally result in a crash,
3569 // but we catch it and return an error
3570 context->handleError(
3571 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003572 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003573 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003574 }
3575
Jiajia Qind9671222016-11-29 16:30:31 +08003576 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003577 {
3578 return false;
3579 }
3580
Jamie Madill2b976812014-08-25 15:47:49 -04003581 // Use max index to validate if our vertex buffers are large enough for the pull.
3582 // TODO: offer fast path, with disabled index validation.
3583 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3584 if (elementArrayBuffer)
3585 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003586 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003587 Error error =
3588 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3589 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003590 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003591 {
Jamie Madill437fa652016-05-03 15:13:24 -04003592 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003593 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003594 }
3595 }
3596 else
3597 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003598 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003599 }
3600
Jamie Madille79b1e12015-11-04 16:36:37 -05003601 // If we use an index greater than our maximum supported index range, return an error.
3602 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3603 // return an error if possible here.
3604 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3605 {
Jamie Madill437fa652016-05-03 15:13:24 -04003606 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003607 return false;
3608 }
3609
Corentin Wallez92db6942016-12-09 13:10:36 -05003610 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3611 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003612 {
3613 return false;
3614 }
3615
Geoff Lang3edfe032015-09-04 16:38:24 -04003616 // No op if there are no real indices in the index data (all are primitive restart).
3617 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003618}
3619
Geoff Langb1196682014-07-23 13:47:29 -04003620bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003621 GLenum mode,
3622 GLsizei count,
3623 GLenum type,
3624 const GLvoid *indices,
3625 GLsizei primcount,
3626 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003627{
3628 if (primcount < 0)
3629 {
Jamie Madill437fa652016-05-03 15:13:24 -04003630 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003631 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003632 }
3633
Jamie Madill2b976812014-08-25 15:47:49 -04003634 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003635 {
3636 return false;
3637 }
3638
3639 // No-op zero primitive count
3640 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003641}
3642
Geoff Lang3edfe032015-09-04 16:38:24 -04003643bool ValidateDrawElementsInstancedANGLE(Context *context,
3644 GLenum mode,
3645 GLsizei count,
3646 GLenum type,
3647 const GLvoid *indices,
3648 GLsizei primcount,
3649 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003650{
3651 if (!ValidateDrawInstancedANGLE(context))
3652 {
3653 return false;
3654 }
3655
He Yunchaoced53ae2016-11-29 15:00:51 +08003656 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3657 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003658}
3659
He Yunchaoced53ae2016-11-29 15:00:51 +08003660bool ValidateFramebufferTextureBase(Context *context,
3661 GLenum target,
3662 GLenum attachment,
3663 GLuint texture,
3664 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003665{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003666 if (!ValidFramebufferTarget(target))
3667 {
Jamie Madill437fa652016-05-03 15:13:24 -04003668 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003669 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003670 }
3671
3672 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003673 {
3674 return false;
3675 }
3676
Jamie Madill55ec3b12014-07-03 10:38:57 -04003677 if (texture != 0)
3678 {
3679 gl::Texture *tex = context->getTexture(texture);
3680
3681 if (tex == NULL)
3682 {
Jamie Madill437fa652016-05-03 15:13:24 -04003683 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003684 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003685 }
3686
3687 if (level < 0)
3688 {
Jamie Madill437fa652016-05-03 15:13:24 -04003689 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003690 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003691 }
3692 }
3693
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003694 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003695 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003696
Jamie Madill84115c92015-04-23 15:00:07 -04003697 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003698 {
Jamie Madill437fa652016-05-03 15:13:24 -04003699 context->handleError(
3700 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003701 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003702 }
3703
3704 return true;
3705}
3706
He Yunchaoced53ae2016-11-29 15:00:51 +08003707bool ValidateFramebufferTexture2D(Context *context,
3708 GLenum target,
3709 GLenum attachment,
3710 GLenum textarget,
3711 GLuint texture,
3712 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003713{
He Yunchaoced53ae2016-11-29 15:00:51 +08003714 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3715 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003716 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3717 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003718 {
Jamie Madill437fa652016-05-03 15:13:24 -04003719 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003720 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003721 }
3722
3723 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003724 {
3725 return false;
3726 }
3727
Jamie Madill55ec3b12014-07-03 10:38:57 -04003728 if (texture != 0)
3729 {
3730 gl::Texture *tex = context->getTexture(texture);
3731 ASSERT(tex);
3732
Jamie Madill2a6564e2014-07-11 09:53:19 -04003733 const gl::Caps &caps = context->getCaps();
3734
Jamie Madill55ec3b12014-07-03 10:38:57 -04003735 switch (textarget)
3736 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003737 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003738 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003739 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003740 {
Jamie Madill437fa652016-05-03 15:13:24 -04003741 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003742 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003743 }
3744 if (tex->getTarget() != GL_TEXTURE_2D)
3745 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003746 context->handleError(Error(GL_INVALID_OPERATION,
3747 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003748 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003749 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003750 }
3751 break;
3752
He Yunchaoced53ae2016-11-29 15:00:51 +08003753 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3754 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3755 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3756 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3757 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3758 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003759 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003760 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003761 {
Jamie Madill437fa652016-05-03 15:13:24 -04003762 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003763 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003764 }
3765 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3766 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003767 context->handleError(Error(GL_INVALID_OPERATION,
3768 "Textarget must match the texture target type."));
3769 return false;
3770 }
3771 }
3772 break;
3773
3774 case GL_TEXTURE_2D_MULTISAMPLE:
3775 {
3776 if (context->getClientVersion() < ES_3_1)
3777 {
3778 context->handleError(Error(GL_INVALID_OPERATION,
3779 "Texture target requires at least OpenGL ES 3.1."));
3780 return false;
3781 }
3782
3783 if (level != 0)
3784 {
3785 context->handleError(
3786 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
3787 return false;
3788 }
3789 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
3790 {
3791 context->handleError(Error(GL_INVALID_OPERATION,
3792 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003793 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003794 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003795 }
3796 break;
3797
He Yunchaoced53ae2016-11-29 15:00:51 +08003798 default:
3799 context->handleError(Error(GL_INVALID_ENUM));
3800 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003801 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003802
Jamie Madilla3944d42016-07-22 22:13:26 -04003803 const Format &format = tex->getFormat(textarget, level);
3804 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003805 {
Jamie Madill437fa652016-05-03 15:13:24 -04003806 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003807 return false;
3808 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003809 }
3810
Jamie Madill570f7c82014-07-03 10:38:54 -04003811 return true;
3812}
3813
Geoff Langb1196682014-07-23 13:47:29 -04003814bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003815{
3816 if (program == 0)
3817 {
Jamie Madill437fa652016-05-03 15:13:24 -04003818 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003819 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003820 }
3821
Dian Xiang769769a2015-09-09 15:20:08 -07003822 gl::Program *programObject = GetValidProgram(context, program);
3823 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003824 {
3825 return false;
3826 }
3827
Jamie Madill0063c512014-08-25 15:47:53 -04003828 if (!programObject || !programObject->isLinked())
3829 {
Jamie Madill437fa652016-05-03 15:13:24 -04003830 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003831 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003832 }
3833
Geoff Lang7dd2e102014-11-10 15:19:26 -05003834 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003835 {
Jamie Madill437fa652016-05-03 15:13:24 -04003836 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003837 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003838 }
3839
Jamie Madill0063c512014-08-25 15:47:53 -04003840 return true;
3841}
3842
He Yunchaoced53ae2016-11-29 15:00:51 +08003843bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003844{
3845 return ValidateGetUniformBase(context, program, location);
3846}
3847
He Yunchaoced53ae2016-11-29 15:00:51 +08003848bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003849{
Jamie Madill78f41802014-08-25 15:47:55 -04003850 return ValidateGetUniformBase(context, program, location);
3851}
3852
Geoff Langf41d0ee2016-10-07 13:04:23 -04003853static bool ValidateSizedGetUniform(Context *context,
3854 GLuint program,
3855 GLint location,
3856 GLsizei bufSize,
3857 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003858{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003859 if (length)
3860 {
3861 *length = 0;
3862 }
3863
Jamie Madill78f41802014-08-25 15:47:55 -04003864 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003865 {
Jamie Madill78f41802014-08-25 15:47:55 -04003866 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003867 }
3868
Geoff Langf41d0ee2016-10-07 13:04:23 -04003869 if (bufSize < 0)
3870 {
3871 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3872 return false;
3873 }
3874
Jamie Madilla502c742014-08-28 17:19:13 -04003875 gl::Program *programObject = context->getProgram(program);
3876 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003877
Jamie Madill78f41802014-08-25 15:47:55 -04003878 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003879 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003880 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003881 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003882 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003883 context->handleError(
3884 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003885 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003886 }
3887
Geoff Langf41d0ee2016-10-07 13:04:23 -04003888 if (length)
3889 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003890 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003891 }
3892
Jamie Madill0063c512014-08-25 15:47:53 -04003893 return true;
3894}
3895
He Yunchaoced53ae2016-11-29 15:00:51 +08003896bool ValidateGetnUniformfvEXT(Context *context,
3897 GLuint program,
3898 GLint location,
3899 GLsizei bufSize,
3900 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003901{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003902 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003903}
3904
He Yunchaoced53ae2016-11-29 15:00:51 +08003905bool ValidateGetnUniformivEXT(Context *context,
3906 GLuint program,
3907 GLint location,
3908 GLsizei bufSize,
3909 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003910{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003911 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3912}
3913
3914bool ValidateGetUniformfvRobustANGLE(Context *context,
3915 GLuint program,
3916 GLint location,
3917 GLsizei bufSize,
3918 GLsizei *length,
3919 GLfloat *params)
3920{
3921 if (!ValidateRobustEntryPoint(context, bufSize))
3922 {
3923 return false;
3924 }
3925
3926 // bufSize is validated in ValidateSizedGetUniform
3927 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3928}
3929
3930bool ValidateGetUniformivRobustANGLE(Context *context,
3931 GLuint program,
3932 GLint location,
3933 GLsizei bufSize,
3934 GLsizei *length,
3935 GLint *params)
3936{
3937 if (!ValidateRobustEntryPoint(context, bufSize))
3938 {
3939 return false;
3940 }
3941
3942 // bufSize is validated in ValidateSizedGetUniform
3943 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3944}
3945
3946bool ValidateGetUniformuivRobustANGLE(Context *context,
3947 GLuint program,
3948 GLint location,
3949 GLsizei bufSize,
3950 GLsizei *length,
3951 GLuint *params)
3952{
3953 if (!ValidateRobustEntryPoint(context, bufSize))
3954 {
3955 return false;
3956 }
3957
3958 if (context->getClientMajorVersion() < 3)
3959 {
3960 context->handleError(
3961 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3962 return false;
3963 }
3964
3965 // bufSize is validated in ValidateSizedGetUniform
3966 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003967}
3968
He Yunchaoced53ae2016-11-29 15:00:51 +08003969bool ValidateDiscardFramebufferBase(Context *context,
3970 GLenum target,
3971 GLsizei numAttachments,
3972 const GLenum *attachments,
3973 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003974{
3975 if (numAttachments < 0)
3976 {
Jamie Madill437fa652016-05-03 15:13:24 -04003977 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003978 return false;
3979 }
3980
3981 for (GLsizei i = 0; i < numAttachments; ++i)
3982 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003983 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003984 {
3985 if (defaultFramebuffer)
3986 {
Jamie Madill437fa652016-05-03 15:13:24 -04003987 context->handleError(Error(
3988 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003989 return false;
3990 }
3991
3992 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3993 {
Jamie Madill437fa652016-05-03 15:13:24 -04003994 context->handleError(Error(GL_INVALID_OPERATION,
3995 "Requested color attachment is greater than the maximum "
3996 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003997 return false;
3998 }
3999 }
4000 else
4001 {
4002 switch (attachments[i])
4003 {
He Yunchaoced53ae2016-11-29 15:00:51 +08004004 case GL_DEPTH_ATTACHMENT:
4005 case GL_STENCIL_ATTACHMENT:
4006 case GL_DEPTH_STENCIL_ATTACHMENT:
4007 if (defaultFramebuffer)
4008 {
4009 context->handleError(
4010 Error(GL_INVALID_ENUM,
4011 "Invalid attachment when the default framebuffer is bound"));
4012 return false;
4013 }
4014 break;
4015 case GL_COLOR:
4016 case GL_DEPTH:
4017 case GL_STENCIL:
4018 if (!defaultFramebuffer)
4019 {
4020 context->handleError(
4021 Error(GL_INVALID_ENUM,
4022 "Invalid attachment when the default framebuffer is not bound"));
4023 return false;
4024 }
4025 break;
4026 default:
4027 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07004028 return false;
Austin Kinross08332632015-05-05 13:35:47 -07004029 }
4030 }
4031 }
4032
4033 return true;
4034}
4035
Austin Kinross6ee1e782015-05-29 17:05:37 -07004036bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
4037{
4038 // Note that debug marker calls must not set error state
4039
4040 if (length < 0)
4041 {
4042 return false;
4043 }
4044
4045 if (marker == nullptr)
4046 {
4047 return false;
4048 }
4049
4050 return true;
4051}
4052
4053bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
4054{
4055 // Note that debug marker calls must not set error state
4056
4057 if (length < 0)
4058 {
4059 return false;
4060 }
4061
4062 if (length > 0 && marker == nullptr)
4063 {
4064 return false;
4065 }
4066
4067 return true;
4068}
4069
Geoff Langdcab33b2015-07-21 13:03:16 -04004070bool ValidateEGLImageTargetTexture2DOES(Context *context,
4071 egl::Display *display,
4072 GLenum target,
4073 egl::Image *image)
4074{
Geoff Langa8406172015-07-21 16:53:39 -04004075 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4076 {
Jamie Madill437fa652016-05-03 15:13:24 -04004077 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004078 return false;
4079 }
4080
4081 switch (target)
4082 {
4083 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004084 if (!context->getExtensions().eglImage)
4085 {
4086 context->handleError(Error(
4087 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4088 }
4089 break;
4090
4091 case GL_TEXTURE_EXTERNAL_OES:
4092 if (!context->getExtensions().eglImageExternal)
4093 {
4094 context->handleError(Error(
4095 GL_INVALID_ENUM,
4096 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4097 }
Geoff Langa8406172015-07-21 16:53:39 -04004098 break;
4099
4100 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004101 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004102 return false;
4103 }
4104
4105 if (!display->isValidImage(image))
4106 {
Jamie Madill437fa652016-05-03 15:13:24 -04004107 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004108 return false;
4109 }
4110
4111 if (image->getSamples() > 0)
4112 {
Jamie Madill437fa652016-05-03 15:13:24 -04004113 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004114 "cannot create a 2D texture from a multisampled EGL image."));
4115 return false;
4116 }
4117
Jamie Madilla3944d42016-07-22 22:13:26 -04004118 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004119 if (!textureCaps.texturable)
4120 {
Jamie Madill437fa652016-05-03 15:13:24 -04004121 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004122 "EGL image internal format is not supported as a texture."));
4123 return false;
4124 }
4125
Geoff Langdcab33b2015-07-21 13:03:16 -04004126 return true;
4127}
4128
4129bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4130 egl::Display *display,
4131 GLenum target,
4132 egl::Image *image)
4133{
Geoff Langa8406172015-07-21 16:53:39 -04004134 if (!context->getExtensions().eglImage)
4135 {
Jamie Madill437fa652016-05-03 15:13:24 -04004136 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004137 return false;
4138 }
4139
4140 switch (target)
4141 {
4142 case GL_RENDERBUFFER:
4143 break;
4144
4145 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004146 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004147 return false;
4148 }
4149
4150 if (!display->isValidImage(image))
4151 {
Jamie Madill437fa652016-05-03 15:13:24 -04004152 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004153 return false;
4154 }
4155
Jamie Madilla3944d42016-07-22 22:13:26 -04004156 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004157 if (!textureCaps.renderable)
4158 {
Jamie Madill437fa652016-05-03 15:13:24 -04004159 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004160 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4161 return false;
4162 }
4163
Geoff Langdcab33b2015-07-21 13:03:16 -04004164 return true;
4165}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004166
4167bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4168{
Geoff Lang36167ab2015-12-07 10:27:14 -05004169 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004170 {
4171 // The default VAO should always exist
4172 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004173 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004174 return false;
4175 }
4176
4177 return true;
4178}
4179
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004180bool ValidateLinkProgram(Context *context, GLuint program)
4181{
4182 if (context->hasActiveTransformFeedback(program))
4183 {
4184 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004185 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004186 "Cannot link program while program is associated with an active "
4187 "transform feedback object."));
4188 return false;
4189 }
4190 return true;
4191}
4192
Geoff Langc5629752015-12-07 16:29:04 -05004193bool ValidateProgramBinaryBase(Context *context,
4194 GLuint program,
4195 GLenum binaryFormat,
4196 const void *binary,
4197 GLint length)
4198{
4199 Program *programObject = GetValidProgram(context, program);
4200 if (programObject == nullptr)
4201 {
4202 return false;
4203 }
4204
4205 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4206 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4207 programBinaryFormats.end())
4208 {
Jamie Madill437fa652016-05-03 15:13:24 -04004209 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004210 return false;
4211 }
4212
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004213 if (context->hasActiveTransformFeedback(program))
4214 {
4215 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004216 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004217 "Cannot change program binary while program is associated with "
4218 "an active transform feedback object."));
4219 return false;
4220 }
4221
Geoff Langc5629752015-12-07 16:29:04 -05004222 return true;
4223}
4224
4225bool ValidateGetProgramBinaryBase(Context *context,
4226 GLuint program,
4227 GLsizei bufSize,
4228 GLsizei *length,
4229 GLenum *binaryFormat,
4230 void *binary)
4231{
4232 Program *programObject = GetValidProgram(context, program);
4233 if (programObject == nullptr)
4234 {
4235 return false;
4236 }
4237
4238 if (!programObject->isLinked())
4239 {
Jamie Madill437fa652016-05-03 15:13:24 -04004240 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004241 return false;
4242 }
4243
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004244 if (context->getCaps().programBinaryFormats.empty())
4245 {
4246 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4247 return false;
4248 }
4249
Geoff Langc5629752015-12-07 16:29:04 -05004250 return true;
4251}
Jamie Madillc29968b2016-01-20 11:17:23 -05004252
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004253bool ValidateUseProgram(Context *context, GLuint program)
4254{
4255 if (program != 0)
4256 {
4257 Program *programObject = context->getProgram(program);
4258 if (!programObject)
4259 {
4260 // ES 3.1.0 section 7.3 page 72
4261 if (context->getShader(program))
4262 {
Jamie Madill437fa652016-05-03 15:13:24 -04004263 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004264 Error(GL_INVALID_OPERATION,
4265 "Attempted to use a single shader instead of a shader program."));
4266 return false;
4267 }
4268 else
4269 {
Jamie Madill437fa652016-05-03 15:13:24 -04004270 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004271 return false;
4272 }
4273 }
4274 if (!programObject->isLinked())
4275 {
Jamie Madill437fa652016-05-03 15:13:24 -04004276 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004277 return false;
4278 }
4279 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004280 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004281 {
4282 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004283 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004284 Error(GL_INVALID_OPERATION,
4285 "Cannot change active program while transform feedback is unpaused."));
4286 return false;
4287 }
4288
4289 return true;
4290}
4291
Jamie Madillc29968b2016-01-20 11:17:23 -05004292bool ValidateCopyTexImage2D(ValidationContext *context,
4293 GLenum target,
4294 GLint level,
4295 GLenum internalformat,
4296 GLint x,
4297 GLint y,
4298 GLsizei width,
4299 GLsizei height,
4300 GLint border)
4301{
Martin Radev1be913c2016-07-11 17:59:16 +03004302 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004303 {
4304 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4305 0, x, y, width, height, border);
4306 }
4307
Martin Radev1be913c2016-07-11 17:59:16 +03004308 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004309 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4310 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004311}
Jamie Madillc29968b2016-01-20 11:17:23 -05004312
4313bool ValidateFramebufferRenderbuffer(Context *context,
4314 GLenum target,
4315 GLenum attachment,
4316 GLenum renderbuffertarget,
4317 GLuint renderbuffer)
4318{
4319 if (!ValidFramebufferTarget(target) ||
4320 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4321 {
Jamie Madill437fa652016-05-03 15:13:24 -04004322 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004323 return false;
4324 }
4325
4326 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4327 renderbuffertarget, renderbuffer);
4328}
4329
4330bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4331{
4332 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4333 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4334 {
Jamie Madill437fa652016-05-03 15:13:24 -04004335 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004336 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4337 return false;
4338 }
4339
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004340 ASSERT(context->getGLState().getDrawFramebuffer());
4341 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004342 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4343
4344 // This should come first before the check for the default frame buffer
4345 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4346 // rather than INVALID_OPERATION
4347 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4348 {
4349 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4350
4351 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004352 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4353 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004354 {
4355 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004356 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4357 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4358 // 3.1 is still a bit ambiguous about the error, but future specs are
4359 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004360 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004361 return false;
4362 }
4363 else if (bufs[colorAttachment] >= maxColorAttachment)
4364 {
Jamie Madill437fa652016-05-03 15:13:24 -04004365 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004366 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004367 return false;
4368 }
4369 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4370 frameBufferId != 0)
4371 {
4372 // INVALID_OPERATION-GL is bound to buffer and ith argument
4373 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004374 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004375 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4376 return false;
4377 }
4378 }
4379
4380 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4381 // and n is not 1 or bufs is bound to value other than BACK and NONE
4382 if (frameBufferId == 0)
4383 {
4384 if (n != 1)
4385 {
Jamie Madill437fa652016-05-03 15:13:24 -04004386 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004387 "n must be 1 when GL is bound to the default framebuffer"));
4388 return false;
4389 }
4390
4391 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4392 {
Jamie Madill437fa652016-05-03 15:13:24 -04004393 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004394 GL_INVALID_OPERATION,
4395 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4396 return false;
4397 }
4398 }
4399
4400 return true;
4401}
4402
4403bool ValidateCopyTexSubImage2D(Context *context,
4404 GLenum target,
4405 GLint level,
4406 GLint xoffset,
4407 GLint yoffset,
4408 GLint x,
4409 GLint y,
4410 GLsizei width,
4411 GLsizei height)
4412{
Martin Radev1be913c2016-07-11 17:59:16 +03004413 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004414 {
4415 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4416 yoffset, x, y, width, height, 0);
4417 }
4418
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004419 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4420 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004421}
4422
Geoff Lang496c02d2016-10-20 11:38:11 -07004423bool ValidateGetBufferPointervBase(Context *context,
4424 GLenum target,
4425 GLenum pname,
4426 GLsizei *length,
4427 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004428{
Geoff Lang496c02d2016-10-20 11:38:11 -07004429 if (length)
4430 {
4431 *length = 0;
4432 }
4433
4434 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4435 {
4436 context->handleError(
4437 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004438 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004439 return false;
4440 }
4441
Olli Etuaho4f667482016-03-30 15:56:35 +03004442 if (!ValidBufferTarget(context, target))
4443 {
Jamie Madill437fa652016-05-03 15:13:24 -04004444 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004445 return false;
4446 }
4447
Geoff Lang496c02d2016-10-20 11:38:11 -07004448 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004449 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004450 case GL_BUFFER_MAP_POINTER:
4451 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004452
Geoff Lang496c02d2016-10-20 11:38:11 -07004453 default:
4454 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4455 return false;
4456 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004457
4458 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4459 // target bound to zero generate an INVALID_OPERATION error."
4460 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004461 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004462 {
Jamie Madill437fa652016-05-03 15:13:24 -04004463 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004464 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4465 return false;
4466 }
4467
Geoff Lang496c02d2016-10-20 11:38:11 -07004468 if (length)
4469 {
4470 *length = 1;
4471 }
4472
Olli Etuaho4f667482016-03-30 15:56:35 +03004473 return true;
4474}
4475
4476bool ValidateUnmapBufferBase(Context *context, GLenum target)
4477{
4478 if (!ValidBufferTarget(context, target))
4479 {
Jamie Madill437fa652016-05-03 15:13:24 -04004480 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004481 return false;
4482 }
4483
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004484 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004485
4486 if (buffer == nullptr || !buffer->isMapped())
4487 {
Jamie Madill437fa652016-05-03 15:13:24 -04004488 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004489 return false;
4490 }
4491
4492 return true;
4493}
4494
4495bool ValidateMapBufferRangeBase(Context *context,
4496 GLenum target,
4497 GLintptr offset,
4498 GLsizeiptr length,
4499 GLbitfield access)
4500{
4501 if (!ValidBufferTarget(context, target))
4502 {
Jamie Madill437fa652016-05-03 15:13:24 -04004503 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004504 return false;
4505 }
4506
4507 if (offset < 0 || length < 0)
4508 {
Jamie Madill437fa652016-05-03 15:13:24 -04004509 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004510 return false;
4511 }
4512
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004513 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004514
4515 if (!buffer)
4516 {
Jamie Madill437fa652016-05-03 15:13:24 -04004517 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004518 return false;
4519 }
4520
4521 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004522 CheckedNumeric<size_t> checkedOffset(offset);
4523 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004524
Jamie Madille2e406c2016-06-02 13:04:10 -04004525 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004526 {
Jamie Madill437fa652016-05-03 15:13:24 -04004527 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004528 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4529 return false;
4530 }
4531
4532 // Check for invalid bits in the mask
4533 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4534 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4535 GL_MAP_UNSYNCHRONIZED_BIT;
4536
4537 if (access & ~(allAccessBits))
4538 {
Jamie Madill437fa652016-05-03 15:13:24 -04004539 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004540 return false;
4541 }
4542
4543 if (length == 0)
4544 {
Jamie Madill437fa652016-05-03 15:13:24 -04004545 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004546 return false;
4547 }
4548
4549 if (buffer->isMapped())
4550 {
Jamie Madill437fa652016-05-03 15:13:24 -04004551 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004552 return false;
4553 }
4554
4555 // Check for invalid bit combinations
4556 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4557 {
Jamie Madill437fa652016-05-03 15:13:24 -04004558 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004559 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4560 return false;
4561 }
4562
4563 GLbitfield writeOnlyBits =
4564 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4565
4566 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4567 {
Jamie Madill437fa652016-05-03 15:13:24 -04004568 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004569 "Invalid access bits when mapping buffer for reading: 0x%X.",
4570 access));
4571 return false;
4572 }
4573
4574 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4575 {
Jamie Madill437fa652016-05-03 15:13:24 -04004576 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004577 GL_INVALID_OPERATION,
4578 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4579 return false;
4580 }
4581 return true;
4582}
4583
4584bool ValidateFlushMappedBufferRangeBase(Context *context,
4585 GLenum target,
4586 GLintptr offset,
4587 GLsizeiptr length)
4588{
4589 if (offset < 0 || length < 0)
4590 {
Jamie Madill437fa652016-05-03 15:13:24 -04004591 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004592 return false;
4593 }
4594
4595 if (!ValidBufferTarget(context, target))
4596 {
Jamie Madill437fa652016-05-03 15:13:24 -04004597 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004598 return false;
4599 }
4600
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004601 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004602
4603 if (buffer == nullptr)
4604 {
Jamie Madill437fa652016-05-03 15:13:24 -04004605 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004606 return false;
4607 }
4608
4609 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4610 {
Jamie Madill437fa652016-05-03 15:13:24 -04004611 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004612 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4613 return false;
4614 }
4615
4616 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004617 CheckedNumeric<size_t> checkedOffset(offset);
4618 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004619
Jamie Madille2e406c2016-06-02 13:04:10 -04004620 if (!checkedSize.IsValid() ||
4621 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004622 {
Jamie Madill437fa652016-05-03 15:13:24 -04004623 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004624 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4625 return false;
4626 }
4627
4628 return true;
4629}
4630
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004631bool ValidateGenerateMipmap(Context *context, GLenum target)
4632{
4633 if (!ValidTextureTarget(context, target))
4634 {
4635 context->handleError(Error(GL_INVALID_ENUM));
4636 return false;
4637 }
4638
4639 Texture *texture = context->getTargetTexture(target);
4640
4641 if (texture == nullptr)
4642 {
4643 context->handleError(Error(GL_INVALID_OPERATION));
4644 return false;
4645 }
4646
4647 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4648
4649 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4650 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4651 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4652 {
4653 context->handleError(Error(GL_INVALID_OPERATION));
4654 return false;
4655 }
4656
Jamie Madilla3944d42016-07-22 22:13:26 -04004657 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4658 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4659 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004660
4661 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4662 // unsized formats or that are color renderable and filterable. Since we do not track if
4663 // the texture was created with sized or unsized format (only sized formats are stored),
4664 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4665 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4666 // textures since they're the only texture format that can be created with unsized formats
4667 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4668 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004669 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4670 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004671 {
4672 context->handleError(Error(GL_INVALID_OPERATION));
4673 return false;
4674 }
4675
4676 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004677 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004678 {
4679 context->handleError(Error(GL_INVALID_OPERATION));
4680 return false;
4681 }
4682
4683 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004684 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004685 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4686 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4687 {
Geoff Lang55482a12016-11-21 16:54:01 -05004688 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004689 context->handleError(Error(GL_INVALID_OPERATION));
4690 return false;
4691 }
4692
4693 // Cube completeness check
4694 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4695 {
4696 context->handleError(Error(GL_INVALID_OPERATION));
4697 return false;
4698 }
4699
4700 return true;
4701}
4702
Olli Etuaho41997e72016-03-10 13:38:39 +02004703bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4704{
4705 return ValidateGenOrDelete(context, n);
4706}
4707
4708bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4709{
4710 return ValidateGenOrDelete(context, n);
4711}
4712
4713bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4714{
4715 return ValidateGenOrDelete(context, n);
4716}
4717
4718bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4719{
4720 return ValidateGenOrDelete(context, n);
4721}
4722
4723bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4724{
4725 return ValidateGenOrDelete(context, n);
4726}
4727
4728bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4729{
4730 return ValidateGenOrDelete(context, n);
4731}
4732
4733bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4734{
4735 return ValidateGenOrDelete(context, n);
4736}
4737
4738bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4739{
4740 return ValidateGenOrDelete(context, n);
4741}
4742
4743bool ValidateGenOrDelete(Context *context, GLint n)
4744{
4745 if (n < 0)
4746 {
Jamie Madill437fa652016-05-03 15:13:24 -04004747 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004748 return false;
4749 }
4750 return true;
4751}
4752
Geoff Langf41a7152016-09-19 15:11:17 -04004753bool ValidateEnable(Context *context, GLenum cap)
4754{
4755 if (!ValidCap(context, cap, false))
4756 {
4757 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4758 return false;
4759 }
4760
4761 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4762 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4763 {
4764 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4765 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4766
4767 // We also output an error message to the debugger window if tracing is active, so that
4768 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05004769 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04004770 return false;
4771 }
4772
4773 return true;
4774}
4775
4776bool ValidateDisable(Context *context, GLenum cap)
4777{
4778 if (!ValidCap(context, cap, false))
4779 {
4780 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4781 return false;
4782 }
4783
4784 return true;
4785}
4786
4787bool ValidateIsEnabled(Context *context, GLenum cap)
4788{
4789 if (!ValidCap(context, cap, true))
4790 {
4791 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4792 return false;
4793 }
4794
4795 return true;
4796}
4797
Geoff Langff5b2d52016-09-07 11:32:23 -04004798bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4799{
4800 if (!context->getExtensions().robustClientMemory)
4801 {
4802 context->handleError(
4803 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4804 return false;
4805 }
4806
4807 if (bufSize < 0)
4808 {
4809 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4810 return false;
4811 }
4812
4813 return true;
4814}
4815
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004816bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4817{
4818 if (bufSize < numParams)
4819 {
4820 context->handleError(Error(GL_INVALID_OPERATION,
4821 "%u parameters are required but %i were provided.", numParams,
4822 bufSize));
4823 return false;
4824 }
4825
4826 return true;
4827}
4828
Geoff Langff5b2d52016-09-07 11:32:23 -04004829bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4830 GLenum target,
4831 GLenum attachment,
4832 GLenum pname,
4833 GLsizei *numParams)
4834{
4835 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4836 *numParams = 1;
4837
4838 if (!ValidFramebufferTarget(target))
4839 {
4840 context->handleError(Error(GL_INVALID_ENUM));
4841 return false;
4842 }
4843
4844 int clientVersion = context->getClientMajorVersion();
4845
4846 switch (pname)
4847 {
4848 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4849 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4850 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4851 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4852 break;
4853
4854 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4855 if (clientVersion < 3 && !context->getExtensions().sRGB)
4856 {
4857 context->handleError(Error(GL_INVALID_ENUM));
4858 return false;
4859 }
4860 break;
4861
4862 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4863 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4864 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4865 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4866 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4867 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4868 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4869 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4870 if (clientVersion < 3)
4871 {
4872 context->handleError(Error(GL_INVALID_ENUM));
4873 return false;
4874 }
4875 break;
4876
4877 default:
4878 context->handleError(Error(GL_INVALID_ENUM));
4879 return false;
4880 }
4881
4882 // Determine if the attachment is a valid enum
4883 switch (attachment)
4884 {
4885 case GL_BACK:
4886 case GL_FRONT:
4887 case GL_DEPTH:
4888 case GL_STENCIL:
4889 case GL_DEPTH_STENCIL_ATTACHMENT:
4890 if (clientVersion < 3)
4891 {
4892 context->handleError(Error(GL_INVALID_ENUM));
4893 return false;
4894 }
4895 break;
4896
4897 case GL_DEPTH_ATTACHMENT:
4898 case GL_STENCIL_ATTACHMENT:
4899 break;
4900
4901 default:
4902 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4903 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4904 {
4905 context->handleError(Error(GL_INVALID_ENUM));
4906 return false;
4907 }
4908 break;
4909 }
4910
4911 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4912 ASSERT(framebuffer);
4913
4914 if (framebuffer->id() == 0)
4915 {
4916 if (clientVersion < 3)
4917 {
4918 context->handleError(Error(GL_INVALID_OPERATION));
4919 return false;
4920 }
4921
4922 switch (attachment)
4923 {
4924 case GL_BACK:
4925 case GL_DEPTH:
4926 case GL_STENCIL:
4927 break;
4928
4929 default:
4930 context->handleError(Error(GL_INVALID_OPERATION));
4931 return false;
4932 }
4933 }
4934 else
4935 {
4936 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4937 {
4938 // Valid attachment query
4939 }
4940 else
4941 {
4942 switch (attachment)
4943 {
4944 case GL_DEPTH_ATTACHMENT:
4945 case GL_STENCIL_ATTACHMENT:
4946 break;
4947
4948 case GL_DEPTH_STENCIL_ATTACHMENT:
4949 if (!framebuffer->hasValidDepthStencil())
4950 {
4951 context->handleError(Error(GL_INVALID_OPERATION));
4952 return false;
4953 }
4954 break;
4955
4956 default:
4957 context->handleError(Error(GL_INVALID_OPERATION));
4958 return false;
4959 }
4960 }
4961 }
4962
4963 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4964 if (attachmentObject)
4965 {
4966 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4967 attachmentObject->type() == GL_TEXTURE ||
4968 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4969
4970 switch (pname)
4971 {
4972 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4973 if (attachmentObject->type() != GL_RENDERBUFFER &&
4974 attachmentObject->type() != GL_TEXTURE)
4975 {
4976 context->handleError(Error(GL_INVALID_ENUM));
4977 return false;
4978 }
4979 break;
4980
4981 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4982 if (attachmentObject->type() != GL_TEXTURE)
4983 {
4984 context->handleError(Error(GL_INVALID_ENUM));
4985 return false;
4986 }
4987 break;
4988
4989 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4990 if (attachmentObject->type() != GL_TEXTURE)
4991 {
4992 context->handleError(Error(GL_INVALID_ENUM));
4993 return false;
4994 }
4995 break;
4996
4997 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4998 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4999 {
5000 context->handleError(Error(GL_INVALID_OPERATION));
5001 return false;
5002 }
5003 break;
5004
5005 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
5006 if (attachmentObject->type() != GL_TEXTURE)
5007 {
5008 context->handleError(Error(GL_INVALID_ENUM));
5009 return false;
5010 }
5011 break;
5012
5013 default:
5014 break;
5015 }
5016 }
5017 else
5018 {
5019 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
5020 // is NONE, then querying any other pname will generate INVALID_ENUM.
5021
5022 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
5023 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
5024 // INVALID_OPERATION for all other pnames
5025
5026 switch (pname)
5027 {
5028 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5029 break;
5030
5031 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5032 if (clientVersion < 3)
5033 {
5034 context->handleError(Error(GL_INVALID_ENUM));
5035 return false;
5036 }
5037 break;
5038
5039 default:
5040 if (clientVersion < 3)
5041 {
5042 context->handleError(Error(GL_INVALID_ENUM));
5043 return false;
5044 }
5045 else
5046 {
5047 context->handleError(Error(GL_INVALID_OPERATION));
5048 return false;
5049 }
5050 }
5051 }
5052
5053 return true;
5054}
5055
5056bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5057 GLenum target,
5058 GLenum attachment,
5059 GLenum pname,
5060 GLsizei bufSize,
5061 GLsizei *numParams)
5062{
5063 if (!ValidateRobustEntryPoint(context, bufSize))
5064 {
5065 return false;
5066 }
5067
5068 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5069 {
5070 return false;
5071 }
5072
5073 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5074 {
5075 return false;
5076 }
5077
5078 return true;
5079}
5080
5081bool ValidateGetBufferParameteriv(ValidationContext *context,
5082 GLenum target,
5083 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005084 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005085{
Geoff Langebebe1c2016-10-14 12:01:31 -04005086 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005087}
5088
5089bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5090 GLenum target,
5091 GLenum pname,
5092 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005093 GLsizei *length,
5094 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005095{
5096 if (!ValidateRobustEntryPoint(context, bufSize))
5097 {
5098 return false;
5099 }
5100
Geoff Langebebe1c2016-10-14 12:01:31 -04005101 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005102 {
5103 return false;
5104 }
5105
Geoff Langebebe1c2016-10-14 12:01:31 -04005106 if (!ValidateRobustBufferSize(context, bufSize, *length))
5107 {
5108 return false;
5109 }
5110
5111 return true;
5112}
5113
5114bool ValidateGetBufferParameteri64v(ValidationContext *context,
5115 GLenum target,
5116 GLenum pname,
5117 GLint64 *params)
5118{
5119 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5120}
5121
5122bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5123 GLenum target,
5124 GLenum pname,
5125 GLsizei bufSize,
5126 GLsizei *length,
5127 GLint64 *params)
5128{
5129 if (!ValidateRobustEntryPoint(context, bufSize))
5130 {
5131 return false;
5132 }
5133
5134 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5135 {
5136 return false;
5137 }
5138
5139 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005140 {
5141 return false;
5142 }
5143
5144 return true;
5145}
5146
5147bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5148{
5149 // Currently, all GetProgramiv queries return 1 parameter
5150 *numParams = 1;
5151
5152 Program *programObject = GetValidProgram(context, program);
5153 if (!programObject)
5154 {
5155 return false;
5156 }
5157
5158 switch (pname)
5159 {
5160 case GL_DELETE_STATUS:
5161 case GL_LINK_STATUS:
5162 case GL_VALIDATE_STATUS:
5163 case GL_INFO_LOG_LENGTH:
5164 case GL_ATTACHED_SHADERS:
5165 case GL_ACTIVE_ATTRIBUTES:
5166 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5167 case GL_ACTIVE_UNIFORMS:
5168 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5169 break;
5170
5171 case GL_PROGRAM_BINARY_LENGTH:
5172 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5173 {
5174 context->handleError(Error(GL_INVALID_ENUM,
5175 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5176 "GL_OES_get_program_binary or ES 3.0."));
5177 return false;
5178 }
5179 break;
5180
5181 case GL_ACTIVE_UNIFORM_BLOCKS:
5182 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5183 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5184 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5185 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5186 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5187 if (context->getClientMajorVersion() < 3)
5188 {
5189 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5190 return false;
5191 }
5192 break;
5193
5194 default:
5195 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5196 return false;
5197 }
5198
5199 return true;
5200}
5201
5202bool ValidateGetProgramivRobustANGLE(Context *context,
5203 GLuint program,
5204 GLenum pname,
5205 GLsizei bufSize,
5206 GLsizei *numParams)
5207{
5208 if (!ValidateRobustEntryPoint(context, bufSize))
5209 {
5210 return false;
5211 }
5212
5213 if (!ValidateGetProgramiv(context, program, pname, numParams))
5214 {
5215 return false;
5216 }
5217
5218 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5219 {
5220 return false;
5221 }
5222
5223 return true;
5224}
5225
Geoff Lang740d9022016-10-07 11:20:52 -04005226bool ValidateGetRenderbufferParameteriv(Context *context,
5227 GLenum target,
5228 GLenum pname,
5229 GLint *params)
5230{
5231 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5232}
5233
5234bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5235 GLenum target,
5236 GLenum pname,
5237 GLsizei bufSize,
5238 GLsizei *length,
5239 GLint *params)
5240{
5241 if (!ValidateRobustEntryPoint(context, bufSize))
5242 {
5243 return false;
5244 }
5245
5246 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5247 {
5248 return false;
5249 }
5250
5251 if (!ValidateRobustBufferSize(context, bufSize, *length))
5252 {
5253 return false;
5254 }
5255
5256 return true;
5257}
5258
Geoff Langd7d0ed32016-10-07 11:33:51 -04005259bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5260{
5261 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5262}
5263
5264bool ValidateGetShaderivRobustANGLE(Context *context,
5265 GLuint shader,
5266 GLenum pname,
5267 GLsizei bufSize,
5268 GLsizei *length,
5269 GLint *params)
5270{
5271 if (!ValidateRobustEntryPoint(context, bufSize))
5272 {
5273 return false;
5274 }
5275
5276 if (!ValidateGetShaderivBase(context, shader, pname, length))
5277 {
5278 return false;
5279 }
5280
5281 if (!ValidateRobustBufferSize(context, bufSize, *length))
5282 {
5283 return false;
5284 }
5285
5286 return true;
5287}
5288
Geoff Langc1984ed2016-10-07 12:41:00 -04005289bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5290{
5291 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5292}
5293
5294bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5295 GLenum target,
5296 GLenum pname,
5297 GLsizei bufSize,
5298 GLsizei *length,
5299 GLfloat *params)
5300{
5301 if (!ValidateRobustEntryPoint(context, bufSize))
5302 {
5303 return false;
5304 }
5305
5306 if (!ValidateGetTexParameterBase(context, target, pname, length))
5307 {
5308 return false;
5309 }
5310
5311 if (!ValidateRobustBufferSize(context, bufSize, *length))
5312 {
5313 return false;
5314 }
5315
5316 return true;
5317}
5318
5319bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5320{
5321 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5322}
5323
5324bool ValidateGetTexParameterivRobustANGLE(Context *context,
5325 GLenum target,
5326 GLenum pname,
5327 GLsizei bufSize,
5328 GLsizei *length,
5329 GLint *params)
5330{
5331 if (!ValidateRobustEntryPoint(context, bufSize))
5332 {
5333 return false;
5334 }
5335
5336 if (!ValidateGetTexParameterBase(context, target, pname, length))
5337 {
5338 return false;
5339 }
5340
5341 if (!ValidateRobustBufferSize(context, bufSize, *length))
5342 {
5343 return false;
5344 }
5345
5346 return true;
5347}
5348
5349bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5350{
5351 return ValidateTexParameterBase(context, target, pname, -1, &param);
5352}
5353
5354bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5355{
5356 return ValidateTexParameterBase(context, target, pname, -1, params);
5357}
5358
5359bool ValidateTexParameterfvRobustANGLE(Context *context,
5360 GLenum target,
5361 GLenum pname,
5362 GLsizei bufSize,
5363 const GLfloat *params)
5364{
5365 if (!ValidateRobustEntryPoint(context, bufSize))
5366 {
5367 return false;
5368 }
5369
5370 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5371}
5372
5373bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5374{
5375 return ValidateTexParameterBase(context, target, pname, -1, &param);
5376}
5377
5378bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5379{
5380 return ValidateTexParameterBase(context, target, pname, -1, params);
5381}
5382
5383bool ValidateTexParameterivRobustANGLE(Context *context,
5384 GLenum target,
5385 GLenum pname,
5386 GLsizei bufSize,
5387 const GLint *params)
5388{
5389 if (!ValidateRobustEntryPoint(context, bufSize))
5390 {
5391 return false;
5392 }
5393
5394 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5395}
5396
5397bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5398{
5399 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5400}
5401
5402bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5403 GLuint sampler,
5404 GLenum pname,
5405 GLuint bufSize,
5406 GLsizei *length,
5407 GLfloat *params)
5408{
5409 if (!ValidateRobustEntryPoint(context, bufSize))
5410 {
5411 return false;
5412 }
5413
5414 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5415 {
5416 return false;
5417 }
5418
5419 if (!ValidateRobustBufferSize(context, bufSize, *length))
5420 {
5421 return false;
5422 }
5423
5424 return true;
5425}
5426
5427bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5428{
5429 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5430}
5431
5432bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5433 GLuint sampler,
5434 GLenum pname,
5435 GLuint bufSize,
5436 GLsizei *length,
5437 GLint *params)
5438{
5439 if (!ValidateRobustEntryPoint(context, bufSize))
5440 {
5441 return false;
5442 }
5443
5444 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5445 {
5446 return false;
5447 }
5448
5449 if (!ValidateRobustBufferSize(context, bufSize, *length))
5450 {
5451 return false;
5452 }
5453
5454 return true;
5455}
5456
5457bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5458{
5459 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5460}
5461
5462bool ValidateSamplerParameterfv(Context *context,
5463 GLuint sampler,
5464 GLenum pname,
5465 const GLfloat *params)
5466{
5467 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5468}
5469
5470bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5471 GLuint sampler,
5472 GLenum pname,
5473 GLsizei bufSize,
5474 const GLfloat *params)
5475{
5476 if (!ValidateRobustEntryPoint(context, bufSize))
5477 {
5478 return false;
5479 }
5480
5481 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5482}
5483
5484bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5485{
5486 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5487}
5488
5489bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5490{
5491 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5492}
5493
5494bool ValidateSamplerParameterivRobustANGLE(Context *context,
5495 GLuint sampler,
5496 GLenum pname,
5497 GLsizei bufSize,
5498 const GLint *params)
5499{
5500 if (!ValidateRobustEntryPoint(context, bufSize))
5501 {
5502 return false;
5503 }
5504
5505 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5506}
5507
Geoff Lang0b031062016-10-13 14:30:04 -04005508bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5509{
5510 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5511}
5512
5513bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5514 GLuint index,
5515 GLenum pname,
5516 GLsizei bufSize,
5517 GLsizei *length,
5518 GLfloat *params)
5519{
5520 if (!ValidateRobustEntryPoint(context, bufSize))
5521 {
5522 return false;
5523 }
5524
5525 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5526 {
5527 return false;
5528 }
5529
5530 if (!ValidateRobustBufferSize(context, bufSize, *length))
5531 {
5532 return false;
5533 }
5534
5535 return true;
5536}
5537
5538bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5539{
5540 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5541}
5542
5543bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5544 GLuint index,
5545 GLenum pname,
5546 GLsizei bufSize,
5547 GLsizei *length,
5548 GLint *params)
5549{
5550 if (!ValidateRobustEntryPoint(context, bufSize))
5551 {
5552 return false;
5553 }
5554
5555 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5556 {
5557 return false;
5558 }
5559
5560 if (!ValidateRobustBufferSize(context, bufSize, *length))
5561 {
5562 return false;
5563 }
5564
5565 return true;
5566}
5567
5568bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5569{
5570 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5571}
5572
5573bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5574 GLuint index,
5575 GLenum pname,
5576 GLsizei bufSize,
5577 GLsizei *length,
5578 void **pointer)
5579{
5580 if (!ValidateRobustEntryPoint(context, bufSize))
5581 {
5582 return false;
5583 }
5584
5585 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5586 {
5587 return false;
5588 }
5589
5590 if (!ValidateRobustBufferSize(context, bufSize, *length))
5591 {
5592 return false;
5593 }
5594
5595 return true;
5596}
5597
5598bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5599{
5600 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5601}
5602
5603bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5604 GLuint index,
5605 GLenum pname,
5606 GLsizei bufSize,
5607 GLsizei *length,
5608 GLint *params)
5609{
5610 if (!ValidateRobustEntryPoint(context, bufSize))
5611 {
5612 return false;
5613 }
5614
5615 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5616 {
5617 return false;
5618 }
5619
5620 if (!ValidateRobustBufferSize(context, bufSize, *length))
5621 {
5622 return false;
5623 }
5624
5625 return true;
5626}
5627
5628bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5629{
5630 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5631}
5632
5633bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5634 GLuint index,
5635 GLenum pname,
5636 GLsizei bufSize,
5637 GLsizei *length,
5638 GLuint *params)
5639{
5640 if (!ValidateRobustEntryPoint(context, bufSize))
5641 {
5642 return false;
5643 }
5644
5645 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5646 {
5647 return false;
5648 }
5649
5650 if (!ValidateRobustBufferSize(context, bufSize, *length))
5651 {
5652 return false;
5653 }
5654
5655 return true;
5656}
5657
Geoff Lang6899b872016-10-14 11:30:13 -04005658bool ValidateGetActiveUniformBlockiv(Context *context,
5659 GLuint program,
5660 GLuint uniformBlockIndex,
5661 GLenum pname,
5662 GLint *params)
5663{
5664 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5665}
5666
5667bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5668 GLuint program,
5669 GLuint uniformBlockIndex,
5670 GLenum pname,
5671 GLsizei bufSize,
5672 GLsizei *length,
5673 GLint *params)
5674{
5675 if (!ValidateRobustEntryPoint(context, bufSize))
5676 {
5677 return false;
5678 }
5679
5680 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5681 {
5682 return false;
5683 }
5684
5685 if (!ValidateRobustBufferSize(context, bufSize, *length))
5686 {
5687 return false;
5688 }
5689
5690 return true;
5691}
5692
Geoff Lang0a9661f2016-10-20 10:59:20 -07005693bool ValidateGetInternalFormativ(Context *context,
5694 GLenum target,
5695 GLenum internalformat,
5696 GLenum pname,
5697 GLsizei bufSize,
5698 GLint *params)
5699{
5700 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5701 nullptr);
5702}
5703
5704bool ValidateGetInternalFormativRobustANGLE(Context *context,
5705 GLenum target,
5706 GLenum internalformat,
5707 GLenum pname,
5708 GLsizei bufSize,
5709 GLsizei *length,
5710 GLint *params)
5711{
5712 if (!ValidateRobustEntryPoint(context, bufSize))
5713 {
5714 return false;
5715 }
5716
5717 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5718 {
5719 return false;
5720 }
5721
5722 if (!ValidateRobustBufferSize(context, bufSize, *length))
5723 {
5724 return false;
5725 }
5726
5727 return true;
5728}
5729
Jamie Madillc29968b2016-01-20 11:17:23 -05005730} // namespace gl