blob: 6901b540636247637a93d94324cbf91a298825de [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 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003506 }
3507
3508 if (context->getExtensions().webglCompatibility ||
3509 !context->getGLState().areClientArraysEnabled())
3510 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003511 if (!elementArrayBuffer && count > 0)
3512 {
3513 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3514 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3515 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3516 context->handleError(Error(GL_INVALID_OPERATION,
3517 "There is no element array buffer bound and count > 0."));
3518 return false;
3519 }
3520 }
3521
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003522 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003523 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003524 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003525 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003526 GLint64 offset = reinterpret_cast<GLint64>(indices);
3527 GLint64 byteCount =
3528 static_cast<GLint64>(typeBytes) * static_cast<GLint64>(count) + offset;
3529
3530 // check for integer overflows
3531 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeBytes) ||
3532 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3533 {
3534 context->handleError(Error(GL_OUT_OF_MEMORY, "Integer overflow."));
3535 return false;
3536 }
3537
3538 // Check for reading past the end of the bound buffer object
3539 if (byteCount > elementArrayBuffer->getSize())
3540 {
3541 context->handleError(
3542 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
3543 return false;
3544 }
3545 }
3546 else if (!indices)
3547 {
3548 // This is an application error that would normally result in a crash,
3549 // but we catch it and return an error
3550 context->handleError(
3551 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003552 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003553 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003554 }
3555
Jiajia Qind9671222016-11-29 16:30:31 +08003556 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003557 {
3558 return false;
3559 }
3560
Jamie Madill2b976812014-08-25 15:47:49 -04003561 // Use max index to validate if our vertex buffers are large enough for the pull.
3562 // TODO: offer fast path, with disabled index validation.
3563 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3564 if (elementArrayBuffer)
3565 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003566 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003567 Error error =
3568 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3569 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003570 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003571 {
Jamie Madill437fa652016-05-03 15:13:24 -04003572 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003573 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003574 }
3575 }
3576 else
3577 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003578 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003579 }
3580
Jamie Madille79b1e12015-11-04 16:36:37 -05003581 // If we use an index greater than our maximum supported index range, return an error.
3582 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3583 // return an error if possible here.
3584 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3585 {
Jamie Madill437fa652016-05-03 15:13:24 -04003586 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003587 return false;
3588 }
3589
Corentin Wallez92db6942016-12-09 13:10:36 -05003590 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3591 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003592 {
3593 return false;
3594 }
3595
Geoff Lang3edfe032015-09-04 16:38:24 -04003596 // No op if there are no real indices in the index data (all are primitive restart).
3597 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003598}
3599
Geoff Langb1196682014-07-23 13:47:29 -04003600bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003601 GLenum mode,
3602 GLsizei count,
3603 GLenum type,
3604 const GLvoid *indices,
3605 GLsizei primcount,
3606 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003607{
3608 if (primcount < 0)
3609 {
Jamie Madill437fa652016-05-03 15:13:24 -04003610 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003611 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003612 }
3613
Jamie Madill2b976812014-08-25 15:47:49 -04003614 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003615 {
3616 return false;
3617 }
3618
3619 // No-op zero primitive count
3620 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003621}
3622
Geoff Lang3edfe032015-09-04 16:38:24 -04003623bool ValidateDrawElementsInstancedANGLE(Context *context,
3624 GLenum mode,
3625 GLsizei count,
3626 GLenum type,
3627 const GLvoid *indices,
3628 GLsizei primcount,
3629 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003630{
3631 if (!ValidateDrawInstancedANGLE(context))
3632 {
3633 return false;
3634 }
3635
He Yunchaoced53ae2016-11-29 15:00:51 +08003636 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3637 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003638}
3639
He Yunchaoced53ae2016-11-29 15:00:51 +08003640bool ValidateFramebufferTextureBase(Context *context,
3641 GLenum target,
3642 GLenum attachment,
3643 GLuint texture,
3644 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003645{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003646 if (!ValidFramebufferTarget(target))
3647 {
Jamie Madill437fa652016-05-03 15:13:24 -04003648 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003649 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003650 }
3651
3652 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003653 {
3654 return false;
3655 }
3656
Jamie Madill55ec3b12014-07-03 10:38:57 -04003657 if (texture != 0)
3658 {
3659 gl::Texture *tex = context->getTexture(texture);
3660
3661 if (tex == NULL)
3662 {
Jamie Madill437fa652016-05-03 15:13:24 -04003663 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003664 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003665 }
3666
3667 if (level < 0)
3668 {
Jamie Madill437fa652016-05-03 15:13:24 -04003669 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003670 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003671 }
3672 }
3673
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003674 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003675 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003676
Jamie Madill84115c92015-04-23 15:00:07 -04003677 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003678 {
Jamie Madill437fa652016-05-03 15:13:24 -04003679 context->handleError(
3680 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003681 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003682 }
3683
3684 return true;
3685}
3686
He Yunchaoced53ae2016-11-29 15:00:51 +08003687bool ValidateFramebufferTexture2D(Context *context,
3688 GLenum target,
3689 GLenum attachment,
3690 GLenum textarget,
3691 GLuint texture,
3692 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003693{
He Yunchaoced53ae2016-11-29 15:00:51 +08003694 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3695 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003696 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3697 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003698 {
Jamie Madill437fa652016-05-03 15:13:24 -04003699 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003700 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003701 }
3702
3703 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003704 {
3705 return false;
3706 }
3707
Jamie Madill55ec3b12014-07-03 10:38:57 -04003708 if (texture != 0)
3709 {
3710 gl::Texture *tex = context->getTexture(texture);
3711 ASSERT(tex);
3712
Jamie Madill2a6564e2014-07-11 09:53:19 -04003713 const gl::Caps &caps = context->getCaps();
3714
Jamie Madill55ec3b12014-07-03 10:38:57 -04003715 switch (textarget)
3716 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003717 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003718 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003719 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003720 {
Jamie Madill437fa652016-05-03 15:13:24 -04003721 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003722 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003723 }
3724 if (tex->getTarget() != GL_TEXTURE_2D)
3725 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003726 context->handleError(Error(GL_INVALID_OPERATION,
3727 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003728 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003729 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003730 }
3731 break;
3732
He Yunchaoced53ae2016-11-29 15:00:51 +08003733 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3734 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3735 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3736 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3737 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3738 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003739 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003740 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003741 {
Jamie Madill437fa652016-05-03 15:13:24 -04003742 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003743 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003744 }
3745 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3746 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003747 context->handleError(Error(GL_INVALID_OPERATION,
3748 "Textarget must match the texture target type."));
3749 return false;
3750 }
3751 }
3752 break;
3753
3754 case GL_TEXTURE_2D_MULTISAMPLE:
3755 {
3756 if (context->getClientVersion() < ES_3_1)
3757 {
3758 context->handleError(Error(GL_INVALID_OPERATION,
3759 "Texture target requires at least OpenGL ES 3.1."));
3760 return false;
3761 }
3762
3763 if (level != 0)
3764 {
3765 context->handleError(
3766 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
3767 return false;
3768 }
3769 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
3770 {
3771 context->handleError(Error(GL_INVALID_OPERATION,
3772 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003773 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003774 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003775 }
3776 break;
3777
He Yunchaoced53ae2016-11-29 15:00:51 +08003778 default:
3779 context->handleError(Error(GL_INVALID_ENUM));
3780 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003781 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003782
Jamie Madilla3944d42016-07-22 22:13:26 -04003783 const Format &format = tex->getFormat(textarget, level);
3784 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003785 {
Jamie Madill437fa652016-05-03 15:13:24 -04003786 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003787 return false;
3788 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003789 }
3790
Jamie Madill570f7c82014-07-03 10:38:54 -04003791 return true;
3792}
3793
Geoff Langb1196682014-07-23 13:47:29 -04003794bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003795{
3796 if (program == 0)
3797 {
Jamie Madill437fa652016-05-03 15:13:24 -04003798 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003799 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003800 }
3801
Dian Xiang769769a2015-09-09 15:20:08 -07003802 gl::Program *programObject = GetValidProgram(context, program);
3803 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003804 {
3805 return false;
3806 }
3807
Jamie Madill0063c512014-08-25 15:47:53 -04003808 if (!programObject || !programObject->isLinked())
3809 {
Jamie Madill437fa652016-05-03 15:13:24 -04003810 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003811 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003812 }
3813
Geoff Lang7dd2e102014-11-10 15:19:26 -05003814 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003815 {
Jamie Madill437fa652016-05-03 15:13:24 -04003816 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003817 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003818 }
3819
Jamie Madill0063c512014-08-25 15:47:53 -04003820 return true;
3821}
3822
He Yunchaoced53ae2016-11-29 15:00:51 +08003823bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003824{
3825 return ValidateGetUniformBase(context, program, location);
3826}
3827
He Yunchaoced53ae2016-11-29 15:00:51 +08003828bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003829{
Jamie Madill78f41802014-08-25 15:47:55 -04003830 return ValidateGetUniformBase(context, program, location);
3831}
3832
Geoff Langf41d0ee2016-10-07 13:04:23 -04003833static bool ValidateSizedGetUniform(Context *context,
3834 GLuint program,
3835 GLint location,
3836 GLsizei bufSize,
3837 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003838{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003839 if (length)
3840 {
3841 *length = 0;
3842 }
3843
Jamie Madill78f41802014-08-25 15:47:55 -04003844 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003845 {
Jamie Madill78f41802014-08-25 15:47:55 -04003846 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003847 }
3848
Geoff Langf41d0ee2016-10-07 13:04:23 -04003849 if (bufSize < 0)
3850 {
3851 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3852 return false;
3853 }
3854
Jamie Madilla502c742014-08-28 17:19:13 -04003855 gl::Program *programObject = context->getProgram(program);
3856 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003857
Jamie Madill78f41802014-08-25 15:47:55 -04003858 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003859 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003860 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003861 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003862 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003863 context->handleError(
3864 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003865 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003866 }
3867
Geoff Langf41d0ee2016-10-07 13:04:23 -04003868 if (length)
3869 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003870 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003871 }
3872
Jamie Madill0063c512014-08-25 15:47:53 -04003873 return true;
3874}
3875
He Yunchaoced53ae2016-11-29 15:00:51 +08003876bool ValidateGetnUniformfvEXT(Context *context,
3877 GLuint program,
3878 GLint location,
3879 GLsizei bufSize,
3880 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003881{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003882 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003883}
3884
He Yunchaoced53ae2016-11-29 15:00:51 +08003885bool ValidateGetnUniformivEXT(Context *context,
3886 GLuint program,
3887 GLint location,
3888 GLsizei bufSize,
3889 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003890{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003891 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3892}
3893
3894bool ValidateGetUniformfvRobustANGLE(Context *context,
3895 GLuint program,
3896 GLint location,
3897 GLsizei bufSize,
3898 GLsizei *length,
3899 GLfloat *params)
3900{
3901 if (!ValidateRobustEntryPoint(context, bufSize))
3902 {
3903 return false;
3904 }
3905
3906 // bufSize is validated in ValidateSizedGetUniform
3907 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3908}
3909
3910bool ValidateGetUniformivRobustANGLE(Context *context,
3911 GLuint program,
3912 GLint location,
3913 GLsizei bufSize,
3914 GLsizei *length,
3915 GLint *params)
3916{
3917 if (!ValidateRobustEntryPoint(context, bufSize))
3918 {
3919 return false;
3920 }
3921
3922 // bufSize is validated in ValidateSizedGetUniform
3923 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3924}
3925
3926bool ValidateGetUniformuivRobustANGLE(Context *context,
3927 GLuint program,
3928 GLint location,
3929 GLsizei bufSize,
3930 GLsizei *length,
3931 GLuint *params)
3932{
3933 if (!ValidateRobustEntryPoint(context, bufSize))
3934 {
3935 return false;
3936 }
3937
3938 if (context->getClientMajorVersion() < 3)
3939 {
3940 context->handleError(
3941 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3942 return false;
3943 }
3944
3945 // bufSize is validated in ValidateSizedGetUniform
3946 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003947}
3948
He Yunchaoced53ae2016-11-29 15:00:51 +08003949bool ValidateDiscardFramebufferBase(Context *context,
3950 GLenum target,
3951 GLsizei numAttachments,
3952 const GLenum *attachments,
3953 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003954{
3955 if (numAttachments < 0)
3956 {
Jamie Madill437fa652016-05-03 15:13:24 -04003957 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003958 return false;
3959 }
3960
3961 for (GLsizei i = 0; i < numAttachments; ++i)
3962 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003963 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003964 {
3965 if (defaultFramebuffer)
3966 {
Jamie Madill437fa652016-05-03 15:13:24 -04003967 context->handleError(Error(
3968 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003969 return false;
3970 }
3971
3972 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3973 {
Jamie Madill437fa652016-05-03 15:13:24 -04003974 context->handleError(Error(GL_INVALID_OPERATION,
3975 "Requested color attachment is greater than the maximum "
3976 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003977 return false;
3978 }
3979 }
3980 else
3981 {
3982 switch (attachments[i])
3983 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003984 case GL_DEPTH_ATTACHMENT:
3985 case GL_STENCIL_ATTACHMENT:
3986 case GL_DEPTH_STENCIL_ATTACHMENT:
3987 if (defaultFramebuffer)
3988 {
3989 context->handleError(
3990 Error(GL_INVALID_ENUM,
3991 "Invalid attachment when the default framebuffer is bound"));
3992 return false;
3993 }
3994 break;
3995 case GL_COLOR:
3996 case GL_DEPTH:
3997 case GL_STENCIL:
3998 if (!defaultFramebuffer)
3999 {
4000 context->handleError(
4001 Error(GL_INVALID_ENUM,
4002 "Invalid attachment when the default framebuffer is not bound"));
4003 return false;
4004 }
4005 break;
4006 default:
4007 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07004008 return false;
Austin Kinross08332632015-05-05 13:35:47 -07004009 }
4010 }
4011 }
4012
4013 return true;
4014}
4015
Austin Kinross6ee1e782015-05-29 17:05:37 -07004016bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
4017{
4018 // Note that debug marker calls must not set error state
4019
4020 if (length < 0)
4021 {
4022 return false;
4023 }
4024
4025 if (marker == nullptr)
4026 {
4027 return false;
4028 }
4029
4030 return true;
4031}
4032
4033bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
4034{
4035 // Note that debug marker calls must not set error state
4036
4037 if (length < 0)
4038 {
4039 return false;
4040 }
4041
4042 if (length > 0 && marker == nullptr)
4043 {
4044 return false;
4045 }
4046
4047 return true;
4048}
4049
Geoff Langdcab33b2015-07-21 13:03:16 -04004050bool ValidateEGLImageTargetTexture2DOES(Context *context,
4051 egl::Display *display,
4052 GLenum target,
4053 egl::Image *image)
4054{
Geoff Langa8406172015-07-21 16:53:39 -04004055 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4056 {
Jamie Madill437fa652016-05-03 15:13:24 -04004057 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004058 return false;
4059 }
4060
4061 switch (target)
4062 {
4063 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004064 if (!context->getExtensions().eglImage)
4065 {
4066 context->handleError(Error(
4067 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4068 }
4069 break;
4070
4071 case GL_TEXTURE_EXTERNAL_OES:
4072 if (!context->getExtensions().eglImageExternal)
4073 {
4074 context->handleError(Error(
4075 GL_INVALID_ENUM,
4076 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4077 }
Geoff Langa8406172015-07-21 16:53:39 -04004078 break;
4079
4080 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004081 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004082 return false;
4083 }
4084
4085 if (!display->isValidImage(image))
4086 {
Jamie Madill437fa652016-05-03 15:13:24 -04004087 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004088 return false;
4089 }
4090
4091 if (image->getSamples() > 0)
4092 {
Jamie Madill437fa652016-05-03 15:13:24 -04004093 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004094 "cannot create a 2D texture from a multisampled EGL image."));
4095 return false;
4096 }
4097
Jamie Madilla3944d42016-07-22 22:13:26 -04004098 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004099 if (!textureCaps.texturable)
4100 {
Jamie Madill437fa652016-05-03 15:13:24 -04004101 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004102 "EGL image internal format is not supported as a texture."));
4103 return false;
4104 }
4105
Geoff Langdcab33b2015-07-21 13:03:16 -04004106 return true;
4107}
4108
4109bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4110 egl::Display *display,
4111 GLenum target,
4112 egl::Image *image)
4113{
Geoff Langa8406172015-07-21 16:53:39 -04004114 if (!context->getExtensions().eglImage)
4115 {
Jamie Madill437fa652016-05-03 15:13:24 -04004116 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004117 return false;
4118 }
4119
4120 switch (target)
4121 {
4122 case GL_RENDERBUFFER:
4123 break;
4124
4125 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004126 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004127 return false;
4128 }
4129
4130 if (!display->isValidImage(image))
4131 {
Jamie Madill437fa652016-05-03 15:13:24 -04004132 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004133 return false;
4134 }
4135
Jamie Madilla3944d42016-07-22 22:13:26 -04004136 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004137 if (!textureCaps.renderable)
4138 {
Jamie Madill437fa652016-05-03 15:13:24 -04004139 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004140 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4141 return false;
4142 }
4143
Geoff Langdcab33b2015-07-21 13:03:16 -04004144 return true;
4145}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004146
4147bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4148{
Geoff Lang36167ab2015-12-07 10:27:14 -05004149 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004150 {
4151 // The default VAO should always exist
4152 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004153 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004154 return false;
4155 }
4156
4157 return true;
4158}
4159
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004160bool ValidateLinkProgram(Context *context, GLuint program)
4161{
4162 if (context->hasActiveTransformFeedback(program))
4163 {
4164 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004165 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004166 "Cannot link program while program is associated with an active "
4167 "transform feedback object."));
4168 return false;
4169 }
4170 return true;
4171}
4172
Geoff Langc5629752015-12-07 16:29:04 -05004173bool ValidateProgramBinaryBase(Context *context,
4174 GLuint program,
4175 GLenum binaryFormat,
4176 const void *binary,
4177 GLint length)
4178{
4179 Program *programObject = GetValidProgram(context, program);
4180 if (programObject == nullptr)
4181 {
4182 return false;
4183 }
4184
4185 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4186 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4187 programBinaryFormats.end())
4188 {
Jamie Madill437fa652016-05-03 15:13:24 -04004189 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004190 return false;
4191 }
4192
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004193 if (context->hasActiveTransformFeedback(program))
4194 {
4195 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004196 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004197 "Cannot change program binary while program is associated with "
4198 "an active transform feedback object."));
4199 return false;
4200 }
4201
Geoff Langc5629752015-12-07 16:29:04 -05004202 return true;
4203}
4204
4205bool ValidateGetProgramBinaryBase(Context *context,
4206 GLuint program,
4207 GLsizei bufSize,
4208 GLsizei *length,
4209 GLenum *binaryFormat,
4210 void *binary)
4211{
4212 Program *programObject = GetValidProgram(context, program);
4213 if (programObject == nullptr)
4214 {
4215 return false;
4216 }
4217
4218 if (!programObject->isLinked())
4219 {
Jamie Madill437fa652016-05-03 15:13:24 -04004220 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004221 return false;
4222 }
4223
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004224 if (context->getCaps().programBinaryFormats.empty())
4225 {
4226 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4227 return false;
4228 }
4229
Geoff Langc5629752015-12-07 16:29:04 -05004230 return true;
4231}
Jamie Madillc29968b2016-01-20 11:17:23 -05004232
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004233bool ValidateUseProgram(Context *context, GLuint program)
4234{
4235 if (program != 0)
4236 {
4237 Program *programObject = context->getProgram(program);
4238 if (!programObject)
4239 {
4240 // ES 3.1.0 section 7.3 page 72
4241 if (context->getShader(program))
4242 {
Jamie Madill437fa652016-05-03 15:13:24 -04004243 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004244 Error(GL_INVALID_OPERATION,
4245 "Attempted to use a single shader instead of a shader program."));
4246 return false;
4247 }
4248 else
4249 {
Jamie Madill437fa652016-05-03 15:13:24 -04004250 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004251 return false;
4252 }
4253 }
4254 if (!programObject->isLinked())
4255 {
Jamie Madill437fa652016-05-03 15:13:24 -04004256 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004257 return false;
4258 }
4259 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004260 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004261 {
4262 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004263 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004264 Error(GL_INVALID_OPERATION,
4265 "Cannot change active program while transform feedback is unpaused."));
4266 return false;
4267 }
4268
4269 return true;
4270}
4271
Jamie Madillc29968b2016-01-20 11:17:23 -05004272bool ValidateCopyTexImage2D(ValidationContext *context,
4273 GLenum target,
4274 GLint level,
4275 GLenum internalformat,
4276 GLint x,
4277 GLint y,
4278 GLsizei width,
4279 GLsizei height,
4280 GLint border)
4281{
Martin Radev1be913c2016-07-11 17:59:16 +03004282 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004283 {
4284 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4285 0, x, y, width, height, border);
4286 }
4287
Martin Radev1be913c2016-07-11 17:59:16 +03004288 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004289 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4290 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004291}
Jamie Madillc29968b2016-01-20 11:17:23 -05004292
4293bool ValidateFramebufferRenderbuffer(Context *context,
4294 GLenum target,
4295 GLenum attachment,
4296 GLenum renderbuffertarget,
4297 GLuint renderbuffer)
4298{
4299 if (!ValidFramebufferTarget(target) ||
4300 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4301 {
Jamie Madill437fa652016-05-03 15:13:24 -04004302 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004303 return false;
4304 }
4305
4306 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4307 renderbuffertarget, renderbuffer);
4308}
4309
4310bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4311{
4312 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4313 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4314 {
Jamie Madill437fa652016-05-03 15:13:24 -04004315 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004316 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4317 return false;
4318 }
4319
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004320 ASSERT(context->getGLState().getDrawFramebuffer());
4321 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004322 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4323
4324 // This should come first before the check for the default frame buffer
4325 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4326 // rather than INVALID_OPERATION
4327 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4328 {
4329 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4330
4331 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004332 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4333 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004334 {
4335 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004336 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4337 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4338 // 3.1 is still a bit ambiguous about the error, but future specs are
4339 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004340 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004341 return false;
4342 }
4343 else if (bufs[colorAttachment] >= maxColorAttachment)
4344 {
Jamie Madill437fa652016-05-03 15:13:24 -04004345 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004346 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004347 return false;
4348 }
4349 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4350 frameBufferId != 0)
4351 {
4352 // INVALID_OPERATION-GL is bound to buffer and ith argument
4353 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004354 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004355 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4356 return false;
4357 }
4358 }
4359
4360 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4361 // and n is not 1 or bufs is bound to value other than BACK and NONE
4362 if (frameBufferId == 0)
4363 {
4364 if (n != 1)
4365 {
Jamie Madill437fa652016-05-03 15:13:24 -04004366 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004367 "n must be 1 when GL is bound to the default framebuffer"));
4368 return false;
4369 }
4370
4371 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4372 {
Jamie Madill437fa652016-05-03 15:13:24 -04004373 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004374 GL_INVALID_OPERATION,
4375 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4376 return false;
4377 }
4378 }
4379
4380 return true;
4381}
4382
4383bool ValidateCopyTexSubImage2D(Context *context,
4384 GLenum target,
4385 GLint level,
4386 GLint xoffset,
4387 GLint yoffset,
4388 GLint x,
4389 GLint y,
4390 GLsizei width,
4391 GLsizei height)
4392{
Martin Radev1be913c2016-07-11 17:59:16 +03004393 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004394 {
4395 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4396 yoffset, x, y, width, height, 0);
4397 }
4398
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004399 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4400 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004401}
4402
Geoff Lang496c02d2016-10-20 11:38:11 -07004403bool ValidateGetBufferPointervBase(Context *context,
4404 GLenum target,
4405 GLenum pname,
4406 GLsizei *length,
4407 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004408{
Geoff Lang496c02d2016-10-20 11:38:11 -07004409 if (length)
4410 {
4411 *length = 0;
4412 }
4413
4414 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4415 {
4416 context->handleError(
4417 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004418 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004419 return false;
4420 }
4421
Olli Etuaho4f667482016-03-30 15:56:35 +03004422 if (!ValidBufferTarget(context, target))
4423 {
Jamie Madill437fa652016-05-03 15:13:24 -04004424 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004425 return false;
4426 }
4427
Geoff Lang496c02d2016-10-20 11:38:11 -07004428 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004429 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004430 case GL_BUFFER_MAP_POINTER:
4431 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004432
Geoff Lang496c02d2016-10-20 11:38:11 -07004433 default:
4434 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4435 return false;
4436 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004437
4438 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4439 // target bound to zero generate an INVALID_OPERATION error."
4440 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004441 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004442 {
Jamie Madill437fa652016-05-03 15:13:24 -04004443 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004444 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4445 return false;
4446 }
4447
Geoff Lang496c02d2016-10-20 11:38:11 -07004448 if (length)
4449 {
4450 *length = 1;
4451 }
4452
Olli Etuaho4f667482016-03-30 15:56:35 +03004453 return true;
4454}
4455
4456bool ValidateUnmapBufferBase(Context *context, GLenum target)
4457{
4458 if (!ValidBufferTarget(context, target))
4459 {
Jamie Madill437fa652016-05-03 15:13:24 -04004460 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004461 return false;
4462 }
4463
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004464 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004465
4466 if (buffer == nullptr || !buffer->isMapped())
4467 {
Jamie Madill437fa652016-05-03 15:13:24 -04004468 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004469 return false;
4470 }
4471
4472 return true;
4473}
4474
4475bool ValidateMapBufferRangeBase(Context *context,
4476 GLenum target,
4477 GLintptr offset,
4478 GLsizeiptr length,
4479 GLbitfield access)
4480{
4481 if (!ValidBufferTarget(context, target))
4482 {
Jamie Madill437fa652016-05-03 15:13:24 -04004483 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004484 return false;
4485 }
4486
4487 if (offset < 0 || length < 0)
4488 {
Jamie Madill437fa652016-05-03 15:13:24 -04004489 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004490 return false;
4491 }
4492
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004493 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004494
4495 if (!buffer)
4496 {
Jamie Madill437fa652016-05-03 15:13:24 -04004497 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004498 return false;
4499 }
4500
4501 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004502 CheckedNumeric<size_t> checkedOffset(offset);
4503 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004504
Jamie Madille2e406c2016-06-02 13:04:10 -04004505 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004506 {
Jamie Madill437fa652016-05-03 15:13:24 -04004507 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004508 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4509 return false;
4510 }
4511
4512 // Check for invalid bits in the mask
4513 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4514 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4515 GL_MAP_UNSYNCHRONIZED_BIT;
4516
4517 if (access & ~(allAccessBits))
4518 {
Jamie Madill437fa652016-05-03 15:13:24 -04004519 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004520 return false;
4521 }
4522
4523 if (length == 0)
4524 {
Jamie Madill437fa652016-05-03 15:13:24 -04004525 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004526 return false;
4527 }
4528
4529 if (buffer->isMapped())
4530 {
Jamie Madill437fa652016-05-03 15:13:24 -04004531 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004532 return false;
4533 }
4534
4535 // Check for invalid bit combinations
4536 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4537 {
Jamie Madill437fa652016-05-03 15:13:24 -04004538 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004539 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4540 return false;
4541 }
4542
4543 GLbitfield writeOnlyBits =
4544 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4545
4546 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4547 {
Jamie Madill437fa652016-05-03 15:13:24 -04004548 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004549 "Invalid access bits when mapping buffer for reading: 0x%X.",
4550 access));
4551 return false;
4552 }
4553
4554 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4555 {
Jamie Madill437fa652016-05-03 15:13:24 -04004556 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004557 GL_INVALID_OPERATION,
4558 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4559 return false;
4560 }
4561 return true;
4562}
4563
4564bool ValidateFlushMappedBufferRangeBase(Context *context,
4565 GLenum target,
4566 GLintptr offset,
4567 GLsizeiptr length)
4568{
4569 if (offset < 0 || length < 0)
4570 {
Jamie Madill437fa652016-05-03 15:13:24 -04004571 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004572 return false;
4573 }
4574
4575 if (!ValidBufferTarget(context, target))
4576 {
Jamie Madill437fa652016-05-03 15:13:24 -04004577 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004578 return false;
4579 }
4580
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004581 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004582
4583 if (buffer == nullptr)
4584 {
Jamie Madill437fa652016-05-03 15:13:24 -04004585 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004586 return false;
4587 }
4588
4589 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4590 {
Jamie Madill437fa652016-05-03 15:13:24 -04004591 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004592 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4593 return false;
4594 }
4595
4596 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004597 CheckedNumeric<size_t> checkedOffset(offset);
4598 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004599
Jamie Madille2e406c2016-06-02 13:04:10 -04004600 if (!checkedSize.IsValid() ||
4601 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004602 {
Jamie Madill437fa652016-05-03 15:13:24 -04004603 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004604 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4605 return false;
4606 }
4607
4608 return true;
4609}
4610
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004611bool ValidateGenerateMipmap(Context *context, GLenum target)
4612{
4613 if (!ValidTextureTarget(context, target))
4614 {
4615 context->handleError(Error(GL_INVALID_ENUM));
4616 return false;
4617 }
4618
4619 Texture *texture = context->getTargetTexture(target);
4620
4621 if (texture == nullptr)
4622 {
4623 context->handleError(Error(GL_INVALID_OPERATION));
4624 return false;
4625 }
4626
4627 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4628
4629 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4630 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4631 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4632 {
4633 context->handleError(Error(GL_INVALID_OPERATION));
4634 return false;
4635 }
4636
Jamie Madilla3944d42016-07-22 22:13:26 -04004637 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4638 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4639 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004640
4641 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4642 // unsized formats or that are color renderable and filterable. Since we do not track if
4643 // the texture was created with sized or unsized format (only sized formats are stored),
4644 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4645 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4646 // textures since they're the only texture format that can be created with unsized formats
4647 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4648 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004649 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4650 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004651 {
4652 context->handleError(Error(GL_INVALID_OPERATION));
4653 return false;
4654 }
4655
4656 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004657 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004658 {
4659 context->handleError(Error(GL_INVALID_OPERATION));
4660 return false;
4661 }
4662
4663 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004664 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004665 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4666 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4667 {
Geoff Lang55482a12016-11-21 16:54:01 -05004668 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004669 context->handleError(Error(GL_INVALID_OPERATION));
4670 return false;
4671 }
4672
4673 // Cube completeness check
4674 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4675 {
4676 context->handleError(Error(GL_INVALID_OPERATION));
4677 return false;
4678 }
4679
4680 return true;
4681}
4682
Olli Etuaho41997e72016-03-10 13:38:39 +02004683bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4684{
4685 return ValidateGenOrDelete(context, n);
4686}
4687
4688bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4689{
4690 return ValidateGenOrDelete(context, n);
4691}
4692
4693bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4694{
4695 return ValidateGenOrDelete(context, n);
4696}
4697
4698bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4699{
4700 return ValidateGenOrDelete(context, n);
4701}
4702
4703bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4704{
4705 return ValidateGenOrDelete(context, n);
4706}
4707
4708bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4709{
4710 return ValidateGenOrDelete(context, n);
4711}
4712
4713bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4714{
4715 return ValidateGenOrDelete(context, n);
4716}
4717
4718bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4719{
4720 return ValidateGenOrDelete(context, n);
4721}
4722
4723bool ValidateGenOrDelete(Context *context, GLint n)
4724{
4725 if (n < 0)
4726 {
Jamie Madill437fa652016-05-03 15:13:24 -04004727 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004728 return false;
4729 }
4730 return true;
4731}
4732
Geoff Langf41a7152016-09-19 15:11:17 -04004733bool ValidateEnable(Context *context, GLenum cap)
4734{
4735 if (!ValidCap(context, cap, false))
4736 {
4737 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4738 return false;
4739 }
4740
4741 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4742 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4743 {
4744 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4745 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4746
4747 // We also output an error message to the debugger window if tracing is active, so that
4748 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05004749 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04004750 return false;
4751 }
4752
4753 return true;
4754}
4755
4756bool ValidateDisable(Context *context, GLenum cap)
4757{
4758 if (!ValidCap(context, cap, false))
4759 {
4760 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4761 return false;
4762 }
4763
4764 return true;
4765}
4766
4767bool ValidateIsEnabled(Context *context, GLenum cap)
4768{
4769 if (!ValidCap(context, cap, true))
4770 {
4771 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4772 return false;
4773 }
4774
4775 return true;
4776}
4777
Geoff Langff5b2d52016-09-07 11:32:23 -04004778bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4779{
4780 if (!context->getExtensions().robustClientMemory)
4781 {
4782 context->handleError(
4783 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4784 return false;
4785 }
4786
4787 if (bufSize < 0)
4788 {
4789 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4790 return false;
4791 }
4792
4793 return true;
4794}
4795
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004796bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4797{
4798 if (bufSize < numParams)
4799 {
4800 context->handleError(Error(GL_INVALID_OPERATION,
4801 "%u parameters are required but %i were provided.", numParams,
4802 bufSize));
4803 return false;
4804 }
4805
4806 return true;
4807}
4808
Geoff Langff5b2d52016-09-07 11:32:23 -04004809bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4810 GLenum target,
4811 GLenum attachment,
4812 GLenum pname,
4813 GLsizei *numParams)
4814{
4815 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4816 *numParams = 1;
4817
4818 if (!ValidFramebufferTarget(target))
4819 {
4820 context->handleError(Error(GL_INVALID_ENUM));
4821 return false;
4822 }
4823
4824 int clientVersion = context->getClientMajorVersion();
4825
4826 switch (pname)
4827 {
4828 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4829 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4830 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4831 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4832 break;
4833
4834 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4835 if (clientVersion < 3 && !context->getExtensions().sRGB)
4836 {
4837 context->handleError(Error(GL_INVALID_ENUM));
4838 return false;
4839 }
4840 break;
4841
4842 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4843 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4844 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4845 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4846 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4847 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4848 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4849 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4850 if (clientVersion < 3)
4851 {
4852 context->handleError(Error(GL_INVALID_ENUM));
4853 return false;
4854 }
4855 break;
4856
4857 default:
4858 context->handleError(Error(GL_INVALID_ENUM));
4859 return false;
4860 }
4861
4862 // Determine if the attachment is a valid enum
4863 switch (attachment)
4864 {
4865 case GL_BACK:
4866 case GL_FRONT:
4867 case GL_DEPTH:
4868 case GL_STENCIL:
4869 case GL_DEPTH_STENCIL_ATTACHMENT:
4870 if (clientVersion < 3)
4871 {
4872 context->handleError(Error(GL_INVALID_ENUM));
4873 return false;
4874 }
4875 break;
4876
4877 case GL_DEPTH_ATTACHMENT:
4878 case GL_STENCIL_ATTACHMENT:
4879 break;
4880
4881 default:
4882 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4883 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4884 {
4885 context->handleError(Error(GL_INVALID_ENUM));
4886 return false;
4887 }
4888 break;
4889 }
4890
4891 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4892 ASSERT(framebuffer);
4893
4894 if (framebuffer->id() == 0)
4895 {
4896 if (clientVersion < 3)
4897 {
4898 context->handleError(Error(GL_INVALID_OPERATION));
4899 return false;
4900 }
4901
4902 switch (attachment)
4903 {
4904 case GL_BACK:
4905 case GL_DEPTH:
4906 case GL_STENCIL:
4907 break;
4908
4909 default:
4910 context->handleError(Error(GL_INVALID_OPERATION));
4911 return false;
4912 }
4913 }
4914 else
4915 {
4916 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4917 {
4918 // Valid attachment query
4919 }
4920 else
4921 {
4922 switch (attachment)
4923 {
4924 case GL_DEPTH_ATTACHMENT:
4925 case GL_STENCIL_ATTACHMENT:
4926 break;
4927
4928 case GL_DEPTH_STENCIL_ATTACHMENT:
4929 if (!framebuffer->hasValidDepthStencil())
4930 {
4931 context->handleError(Error(GL_INVALID_OPERATION));
4932 return false;
4933 }
4934 break;
4935
4936 default:
4937 context->handleError(Error(GL_INVALID_OPERATION));
4938 return false;
4939 }
4940 }
4941 }
4942
4943 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4944 if (attachmentObject)
4945 {
4946 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4947 attachmentObject->type() == GL_TEXTURE ||
4948 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4949
4950 switch (pname)
4951 {
4952 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4953 if (attachmentObject->type() != GL_RENDERBUFFER &&
4954 attachmentObject->type() != GL_TEXTURE)
4955 {
4956 context->handleError(Error(GL_INVALID_ENUM));
4957 return false;
4958 }
4959 break;
4960
4961 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4962 if (attachmentObject->type() != GL_TEXTURE)
4963 {
4964 context->handleError(Error(GL_INVALID_ENUM));
4965 return false;
4966 }
4967 break;
4968
4969 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4970 if (attachmentObject->type() != GL_TEXTURE)
4971 {
4972 context->handleError(Error(GL_INVALID_ENUM));
4973 return false;
4974 }
4975 break;
4976
4977 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4978 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4979 {
4980 context->handleError(Error(GL_INVALID_OPERATION));
4981 return false;
4982 }
4983 break;
4984
4985 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4986 if (attachmentObject->type() != GL_TEXTURE)
4987 {
4988 context->handleError(Error(GL_INVALID_ENUM));
4989 return false;
4990 }
4991 break;
4992
4993 default:
4994 break;
4995 }
4996 }
4997 else
4998 {
4999 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
5000 // is NONE, then querying any other pname will generate INVALID_ENUM.
5001
5002 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
5003 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
5004 // INVALID_OPERATION for all other pnames
5005
5006 switch (pname)
5007 {
5008 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5009 break;
5010
5011 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5012 if (clientVersion < 3)
5013 {
5014 context->handleError(Error(GL_INVALID_ENUM));
5015 return false;
5016 }
5017 break;
5018
5019 default:
5020 if (clientVersion < 3)
5021 {
5022 context->handleError(Error(GL_INVALID_ENUM));
5023 return false;
5024 }
5025 else
5026 {
5027 context->handleError(Error(GL_INVALID_OPERATION));
5028 return false;
5029 }
5030 }
5031 }
5032
5033 return true;
5034}
5035
5036bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5037 GLenum target,
5038 GLenum attachment,
5039 GLenum pname,
5040 GLsizei bufSize,
5041 GLsizei *numParams)
5042{
5043 if (!ValidateRobustEntryPoint(context, bufSize))
5044 {
5045 return false;
5046 }
5047
5048 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5049 {
5050 return false;
5051 }
5052
5053 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5054 {
5055 return false;
5056 }
5057
5058 return true;
5059}
5060
5061bool ValidateGetBufferParameteriv(ValidationContext *context,
5062 GLenum target,
5063 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005064 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005065{
Geoff Langebebe1c2016-10-14 12:01:31 -04005066 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005067}
5068
5069bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5070 GLenum target,
5071 GLenum pname,
5072 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005073 GLsizei *length,
5074 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005075{
5076 if (!ValidateRobustEntryPoint(context, bufSize))
5077 {
5078 return false;
5079 }
5080
Geoff Langebebe1c2016-10-14 12:01:31 -04005081 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005082 {
5083 return false;
5084 }
5085
Geoff Langebebe1c2016-10-14 12:01:31 -04005086 if (!ValidateRobustBufferSize(context, bufSize, *length))
5087 {
5088 return false;
5089 }
5090
5091 return true;
5092}
5093
5094bool ValidateGetBufferParameteri64v(ValidationContext *context,
5095 GLenum target,
5096 GLenum pname,
5097 GLint64 *params)
5098{
5099 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5100}
5101
5102bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5103 GLenum target,
5104 GLenum pname,
5105 GLsizei bufSize,
5106 GLsizei *length,
5107 GLint64 *params)
5108{
5109 if (!ValidateRobustEntryPoint(context, bufSize))
5110 {
5111 return false;
5112 }
5113
5114 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5115 {
5116 return false;
5117 }
5118
5119 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005120 {
5121 return false;
5122 }
5123
5124 return true;
5125}
5126
5127bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5128{
5129 // Currently, all GetProgramiv queries return 1 parameter
5130 *numParams = 1;
5131
5132 Program *programObject = GetValidProgram(context, program);
5133 if (!programObject)
5134 {
5135 return false;
5136 }
5137
5138 switch (pname)
5139 {
5140 case GL_DELETE_STATUS:
5141 case GL_LINK_STATUS:
5142 case GL_VALIDATE_STATUS:
5143 case GL_INFO_LOG_LENGTH:
5144 case GL_ATTACHED_SHADERS:
5145 case GL_ACTIVE_ATTRIBUTES:
5146 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5147 case GL_ACTIVE_UNIFORMS:
5148 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5149 break;
5150
5151 case GL_PROGRAM_BINARY_LENGTH:
5152 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5153 {
5154 context->handleError(Error(GL_INVALID_ENUM,
5155 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5156 "GL_OES_get_program_binary or ES 3.0."));
5157 return false;
5158 }
5159 break;
5160
5161 case GL_ACTIVE_UNIFORM_BLOCKS:
5162 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5163 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5164 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5165 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5166 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5167 if (context->getClientMajorVersion() < 3)
5168 {
5169 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5170 return false;
5171 }
5172 break;
5173
5174 default:
5175 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5176 return false;
5177 }
5178
5179 return true;
5180}
5181
5182bool ValidateGetProgramivRobustANGLE(Context *context,
5183 GLuint program,
5184 GLenum pname,
5185 GLsizei bufSize,
5186 GLsizei *numParams)
5187{
5188 if (!ValidateRobustEntryPoint(context, bufSize))
5189 {
5190 return false;
5191 }
5192
5193 if (!ValidateGetProgramiv(context, program, pname, numParams))
5194 {
5195 return false;
5196 }
5197
5198 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5199 {
5200 return false;
5201 }
5202
5203 return true;
5204}
5205
Geoff Lang740d9022016-10-07 11:20:52 -04005206bool ValidateGetRenderbufferParameteriv(Context *context,
5207 GLenum target,
5208 GLenum pname,
5209 GLint *params)
5210{
5211 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5212}
5213
5214bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5215 GLenum target,
5216 GLenum pname,
5217 GLsizei bufSize,
5218 GLsizei *length,
5219 GLint *params)
5220{
5221 if (!ValidateRobustEntryPoint(context, bufSize))
5222 {
5223 return false;
5224 }
5225
5226 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5227 {
5228 return false;
5229 }
5230
5231 if (!ValidateRobustBufferSize(context, bufSize, *length))
5232 {
5233 return false;
5234 }
5235
5236 return true;
5237}
5238
Geoff Langd7d0ed32016-10-07 11:33:51 -04005239bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5240{
5241 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5242}
5243
5244bool ValidateGetShaderivRobustANGLE(Context *context,
5245 GLuint shader,
5246 GLenum pname,
5247 GLsizei bufSize,
5248 GLsizei *length,
5249 GLint *params)
5250{
5251 if (!ValidateRobustEntryPoint(context, bufSize))
5252 {
5253 return false;
5254 }
5255
5256 if (!ValidateGetShaderivBase(context, shader, pname, length))
5257 {
5258 return false;
5259 }
5260
5261 if (!ValidateRobustBufferSize(context, bufSize, *length))
5262 {
5263 return false;
5264 }
5265
5266 return true;
5267}
5268
Geoff Langc1984ed2016-10-07 12:41:00 -04005269bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5270{
5271 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5272}
5273
5274bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5275 GLenum target,
5276 GLenum pname,
5277 GLsizei bufSize,
5278 GLsizei *length,
5279 GLfloat *params)
5280{
5281 if (!ValidateRobustEntryPoint(context, bufSize))
5282 {
5283 return false;
5284 }
5285
5286 if (!ValidateGetTexParameterBase(context, target, pname, length))
5287 {
5288 return false;
5289 }
5290
5291 if (!ValidateRobustBufferSize(context, bufSize, *length))
5292 {
5293 return false;
5294 }
5295
5296 return true;
5297}
5298
5299bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5300{
5301 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5302}
5303
5304bool ValidateGetTexParameterivRobustANGLE(Context *context,
5305 GLenum target,
5306 GLenum pname,
5307 GLsizei bufSize,
5308 GLsizei *length,
5309 GLint *params)
5310{
5311 if (!ValidateRobustEntryPoint(context, bufSize))
5312 {
5313 return false;
5314 }
5315
5316 if (!ValidateGetTexParameterBase(context, target, pname, length))
5317 {
5318 return false;
5319 }
5320
5321 if (!ValidateRobustBufferSize(context, bufSize, *length))
5322 {
5323 return false;
5324 }
5325
5326 return true;
5327}
5328
5329bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5330{
5331 return ValidateTexParameterBase(context, target, pname, -1, &param);
5332}
5333
5334bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5335{
5336 return ValidateTexParameterBase(context, target, pname, -1, params);
5337}
5338
5339bool ValidateTexParameterfvRobustANGLE(Context *context,
5340 GLenum target,
5341 GLenum pname,
5342 GLsizei bufSize,
5343 const GLfloat *params)
5344{
5345 if (!ValidateRobustEntryPoint(context, bufSize))
5346 {
5347 return false;
5348 }
5349
5350 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5351}
5352
5353bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5354{
5355 return ValidateTexParameterBase(context, target, pname, -1, &param);
5356}
5357
5358bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5359{
5360 return ValidateTexParameterBase(context, target, pname, -1, params);
5361}
5362
5363bool ValidateTexParameterivRobustANGLE(Context *context,
5364 GLenum target,
5365 GLenum pname,
5366 GLsizei bufSize,
5367 const GLint *params)
5368{
5369 if (!ValidateRobustEntryPoint(context, bufSize))
5370 {
5371 return false;
5372 }
5373
5374 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5375}
5376
5377bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5378{
5379 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5380}
5381
5382bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5383 GLuint sampler,
5384 GLenum pname,
5385 GLuint bufSize,
5386 GLsizei *length,
5387 GLfloat *params)
5388{
5389 if (!ValidateRobustEntryPoint(context, bufSize))
5390 {
5391 return false;
5392 }
5393
5394 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5395 {
5396 return false;
5397 }
5398
5399 if (!ValidateRobustBufferSize(context, bufSize, *length))
5400 {
5401 return false;
5402 }
5403
5404 return true;
5405}
5406
5407bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5408{
5409 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5410}
5411
5412bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5413 GLuint sampler,
5414 GLenum pname,
5415 GLuint bufSize,
5416 GLsizei *length,
5417 GLint *params)
5418{
5419 if (!ValidateRobustEntryPoint(context, bufSize))
5420 {
5421 return false;
5422 }
5423
5424 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5425 {
5426 return false;
5427 }
5428
5429 if (!ValidateRobustBufferSize(context, bufSize, *length))
5430 {
5431 return false;
5432 }
5433
5434 return true;
5435}
5436
5437bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5438{
5439 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5440}
5441
5442bool ValidateSamplerParameterfv(Context *context,
5443 GLuint sampler,
5444 GLenum pname,
5445 const GLfloat *params)
5446{
5447 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5448}
5449
5450bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5451 GLuint sampler,
5452 GLenum pname,
5453 GLsizei bufSize,
5454 const GLfloat *params)
5455{
5456 if (!ValidateRobustEntryPoint(context, bufSize))
5457 {
5458 return false;
5459 }
5460
5461 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5462}
5463
5464bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5465{
5466 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5467}
5468
5469bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5470{
5471 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5472}
5473
5474bool ValidateSamplerParameterivRobustANGLE(Context *context,
5475 GLuint sampler,
5476 GLenum pname,
5477 GLsizei bufSize,
5478 const GLint *params)
5479{
5480 if (!ValidateRobustEntryPoint(context, bufSize))
5481 {
5482 return false;
5483 }
5484
5485 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5486}
5487
Geoff Lang0b031062016-10-13 14:30:04 -04005488bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5489{
5490 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5491}
5492
5493bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5494 GLuint index,
5495 GLenum pname,
5496 GLsizei bufSize,
5497 GLsizei *length,
5498 GLfloat *params)
5499{
5500 if (!ValidateRobustEntryPoint(context, bufSize))
5501 {
5502 return false;
5503 }
5504
5505 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5506 {
5507 return false;
5508 }
5509
5510 if (!ValidateRobustBufferSize(context, bufSize, *length))
5511 {
5512 return false;
5513 }
5514
5515 return true;
5516}
5517
5518bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5519{
5520 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5521}
5522
5523bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5524 GLuint index,
5525 GLenum pname,
5526 GLsizei bufSize,
5527 GLsizei *length,
5528 GLint *params)
5529{
5530 if (!ValidateRobustEntryPoint(context, bufSize))
5531 {
5532 return false;
5533 }
5534
5535 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5536 {
5537 return false;
5538 }
5539
5540 if (!ValidateRobustBufferSize(context, bufSize, *length))
5541 {
5542 return false;
5543 }
5544
5545 return true;
5546}
5547
5548bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5549{
5550 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5551}
5552
5553bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5554 GLuint index,
5555 GLenum pname,
5556 GLsizei bufSize,
5557 GLsizei *length,
5558 void **pointer)
5559{
5560 if (!ValidateRobustEntryPoint(context, bufSize))
5561 {
5562 return false;
5563 }
5564
5565 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5566 {
5567 return false;
5568 }
5569
5570 if (!ValidateRobustBufferSize(context, bufSize, *length))
5571 {
5572 return false;
5573 }
5574
5575 return true;
5576}
5577
5578bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5579{
5580 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5581}
5582
5583bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5584 GLuint index,
5585 GLenum pname,
5586 GLsizei bufSize,
5587 GLsizei *length,
5588 GLint *params)
5589{
5590 if (!ValidateRobustEntryPoint(context, bufSize))
5591 {
5592 return false;
5593 }
5594
5595 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5596 {
5597 return false;
5598 }
5599
5600 if (!ValidateRobustBufferSize(context, bufSize, *length))
5601 {
5602 return false;
5603 }
5604
5605 return true;
5606}
5607
5608bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5609{
5610 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5611}
5612
5613bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5614 GLuint index,
5615 GLenum pname,
5616 GLsizei bufSize,
5617 GLsizei *length,
5618 GLuint *params)
5619{
5620 if (!ValidateRobustEntryPoint(context, bufSize))
5621 {
5622 return false;
5623 }
5624
5625 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5626 {
5627 return false;
5628 }
5629
5630 if (!ValidateRobustBufferSize(context, bufSize, *length))
5631 {
5632 return false;
5633 }
5634
5635 return true;
5636}
5637
Geoff Lang6899b872016-10-14 11:30:13 -04005638bool ValidateGetActiveUniformBlockiv(Context *context,
5639 GLuint program,
5640 GLuint uniformBlockIndex,
5641 GLenum pname,
5642 GLint *params)
5643{
5644 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5645}
5646
5647bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5648 GLuint program,
5649 GLuint uniformBlockIndex,
5650 GLenum pname,
5651 GLsizei bufSize,
5652 GLsizei *length,
5653 GLint *params)
5654{
5655 if (!ValidateRobustEntryPoint(context, bufSize))
5656 {
5657 return false;
5658 }
5659
5660 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5661 {
5662 return false;
5663 }
5664
5665 if (!ValidateRobustBufferSize(context, bufSize, *length))
5666 {
5667 return false;
5668 }
5669
5670 return true;
5671}
5672
Geoff Lang0a9661f2016-10-20 10:59:20 -07005673bool ValidateGetInternalFormativ(Context *context,
5674 GLenum target,
5675 GLenum internalformat,
5676 GLenum pname,
5677 GLsizei bufSize,
5678 GLint *params)
5679{
5680 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5681 nullptr);
5682}
5683
5684bool ValidateGetInternalFormativRobustANGLE(Context *context,
5685 GLenum target,
5686 GLenum internalformat,
5687 GLenum pname,
5688 GLsizei bufSize,
5689 GLsizei *length,
5690 GLint *params)
5691{
5692 if (!ValidateRobustEntryPoint(context, bufSize))
5693 {
5694 return false;
5695 }
5696
5697 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5698 {
5699 return false;
5700 }
5701
5702 if (!ValidateRobustBufferSize(context, bufSize, *length))
5703 {
5704 return false;
5705 }
5706
5707 return true;
5708}
5709
Jamie Madillc29968b2016-01-20 11:17:23 -05005710} // namespace gl