blob: 998557351263bc033d07a6989f3c67a807741d6c [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
Geoff Langf41a7152016-09-19 15:11:17 -0400219 default:
220 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500221 }
222}
223
Geoff Lang62fce5b2016-09-30 10:46:35 -0400224bool ValidateReadPixelsBase(ValidationContext *context,
225 GLint x,
226 GLint y,
227 GLsizei width,
228 GLsizei height,
229 GLenum format,
230 GLenum type,
231 GLsizei bufSize,
232 GLsizei *length,
233 GLvoid *pixels)
234{
235 if (length != nullptr)
236 {
237 *length = 0;
238 }
239
240 if (width < 0 || height < 0)
241 {
242 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
243 return false;
244 }
245
246 auto readFramebuffer = context->getGLState().getReadFramebuffer();
247
248 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
249 {
250 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
251 return false;
252 }
253
254 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
255 {
256 context->handleError(Error(GL_INVALID_OPERATION));
257 return false;
258 }
259
260 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
261 ASSERT(framebuffer);
262
263 if (framebuffer->getReadBufferState() == GL_NONE)
264 {
265 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
266 return false;
267 }
268
269 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500270 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
271 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
272 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
273 // situation is an application error that would lead to a crash in ANGLE.
274 if (readBuffer == nullptr)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400275 {
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500276 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
Geoff Lang62fce5b2016-09-30 10:46:35 -0400277 return false;
278 }
279
280 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
281 GLenum currentType = framebuffer->getImplementationColorReadType();
282 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
283
284 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
285 bool validFormatTypeCombination =
286 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
287
288 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
289 {
290 context->handleError(Error(GL_INVALID_OPERATION));
291 return false;
292 }
293
294 // Check for pixel pack buffer related API errors
295 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
296 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
297 {
298 // ...the buffer object's data store is currently mapped.
299 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
300 return false;
301 }
302
303 // .. the data would be packed to the buffer object such that the memory writes required
304 // would exceed the data store size.
305 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
306 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
307 const gl::Extents size(width, height, 1);
308 const auto &pack = context->getGLState().getPackState();
309
310 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
311 if (endByteOrErr.isError())
312 {
313 context->handleError(endByteOrErr.getError());
314 return false;
315 }
316
317 size_t endByte = endByteOrErr.getResult();
318 if (bufSize >= 0)
319 {
320
321 if (static_cast<size_t>(bufSize) < endByte)
322 {
323 context->handleError(
324 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
325 return false;
326 }
327 }
328
329 if (pixelPackBuffer != nullptr)
330 {
331 CheckedNumeric<size_t> checkedEndByte(endByte);
332 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
333 checkedEndByte += checkedOffset;
334
335 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
336 {
337 // Overflow past the end of the buffer
338 context->handleError(
339 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
340 return false;
341 }
342 }
343
344 if (length != nullptr)
345 {
346 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
347 {
348 context->handleError(
349 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
350 return false;
351 }
352
353 *length = static_cast<GLsizei>(endByte);
354 }
355
356 return true;
357}
358
Geoff Lang740d9022016-10-07 11:20:52 -0400359bool ValidateGetRenderbufferParameterivBase(Context *context,
360 GLenum target,
361 GLenum pname,
362 GLsizei *length)
363{
364 if (length)
365 {
366 *length = 0;
367 }
368
369 if (target != GL_RENDERBUFFER)
370 {
371 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
372 return false;
373 }
374
375 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
376 if (renderbuffer == nullptr)
377 {
378 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
379 return false;
380 }
381
382 switch (pname)
383 {
384 case GL_RENDERBUFFER_WIDTH:
385 case GL_RENDERBUFFER_HEIGHT:
386 case GL_RENDERBUFFER_INTERNAL_FORMAT:
387 case GL_RENDERBUFFER_RED_SIZE:
388 case GL_RENDERBUFFER_GREEN_SIZE:
389 case GL_RENDERBUFFER_BLUE_SIZE:
390 case GL_RENDERBUFFER_ALPHA_SIZE:
391 case GL_RENDERBUFFER_DEPTH_SIZE:
392 case GL_RENDERBUFFER_STENCIL_SIZE:
393 break;
394
395 case GL_RENDERBUFFER_SAMPLES_ANGLE:
396 if (!context->getExtensions().framebufferMultisample)
397 {
398 context->handleError(
399 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
400 return false;
401 }
402 break;
403
404 default:
405 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
406 return false;
407 }
408
409 if (length)
410 {
411 *length = 1;
412 }
413 return true;
414}
415
Geoff Langd7d0ed32016-10-07 11:33:51 -0400416bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
417{
418 if (length)
419 {
420 *length = 0;
421 }
422
423 if (GetValidShader(context, shader) == nullptr)
424 {
425 return false;
426 }
427
428 switch (pname)
429 {
430 case GL_SHADER_TYPE:
431 case GL_DELETE_STATUS:
432 case GL_COMPILE_STATUS:
433 case GL_INFO_LOG_LENGTH:
434 case GL_SHADER_SOURCE_LENGTH:
435 break;
436
437 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
438 if (!context->getExtensions().translatedShaderSource)
439 {
440 context->handleError(
441 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
442 return false;
443 }
444 break;
445
446 default:
447 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
448 return false;
449 }
450
451 if (length)
452 {
453 *length = 1;
454 }
455 return true;
456}
457
Geoff Langc1984ed2016-10-07 12:41:00 -0400458bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
459{
460 if (length)
461 {
462 *length = 0;
463 }
464
465 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
466 {
467 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
468 return false;
469 }
470
471 if (context->getTargetTexture(target) == nullptr)
472 {
473 // Should only be possible for external textures
474 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
475 return false;
476 }
477
478 switch (pname)
479 {
480 case GL_TEXTURE_MAG_FILTER:
481 case GL_TEXTURE_MIN_FILTER:
482 case GL_TEXTURE_WRAP_S:
483 case GL_TEXTURE_WRAP_T:
484 break;
485
486 case GL_TEXTURE_USAGE_ANGLE:
487 if (!context->getExtensions().textureUsage)
488 {
489 context->handleError(
490 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
491 return false;
492 }
493 break;
494
495 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
496 if (!context->getExtensions().textureFilterAnisotropic)
497 {
498 context->handleError(
499 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
500 return false;
501 }
502 break;
503
504 case GL_TEXTURE_IMMUTABLE_FORMAT:
505 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
506 {
507 context->handleError(
508 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
509 return false;
510 }
511 break;
512
513 case GL_TEXTURE_WRAP_R:
514 case GL_TEXTURE_IMMUTABLE_LEVELS:
515 case GL_TEXTURE_SWIZZLE_R:
516 case GL_TEXTURE_SWIZZLE_G:
517 case GL_TEXTURE_SWIZZLE_B:
518 case GL_TEXTURE_SWIZZLE_A:
519 case GL_TEXTURE_BASE_LEVEL:
520 case GL_TEXTURE_MAX_LEVEL:
521 case GL_TEXTURE_MIN_LOD:
522 case GL_TEXTURE_MAX_LOD:
523 case GL_TEXTURE_COMPARE_MODE:
524 case GL_TEXTURE_COMPARE_FUNC:
525 if (context->getClientMajorVersion() < 3)
526 {
527 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
528 return false;
529 }
530 break;
531
Geoff Lang81c6b572016-10-19 14:07:52 -0700532 case GL_TEXTURE_SRGB_DECODE_EXT:
533 if (!context->getExtensions().textureSRGBDecode)
534 {
535 context->handleError(
536 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
537 return false;
538 }
539 break;
540
Geoff Langc1984ed2016-10-07 12:41:00 -0400541 default:
542 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
543 return false;
544 }
545
546 if (length)
547 {
548 *length = 1;
549 }
550 return true;
551}
552
553template <typename ParamType>
554bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
555{
556 switch (ConvertToGLenum(params[0]))
557 {
558 case GL_CLAMP_TO_EDGE:
559 break;
560
561 case GL_REPEAT:
562 case GL_MIRRORED_REPEAT:
563 if (isExternalTextureTarget)
564 {
565 // OES_EGL_image_external specifies this error.
566 context->handleError(Error(
567 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
568 return false;
569 }
570 break;
571
572 default:
573 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
574 return false;
575 }
576
577 return true;
578}
579
580template <typename ParamType>
581bool ValidateTextureMinFilterValue(Context *context,
582 ParamType *params,
583 bool isExternalTextureTarget)
584{
585 switch (ConvertToGLenum(params[0]))
586 {
587 case GL_NEAREST:
588 case GL_LINEAR:
589 break;
590
591 case GL_NEAREST_MIPMAP_NEAREST:
592 case GL_LINEAR_MIPMAP_NEAREST:
593 case GL_NEAREST_MIPMAP_LINEAR:
594 case GL_LINEAR_MIPMAP_LINEAR:
595 if (isExternalTextureTarget)
596 {
597 // OES_EGL_image_external specifies this error.
598 context->handleError(
599 Error(GL_INVALID_ENUM,
600 "external textures only support NEAREST and LINEAR filtering"));
601 return false;
602 }
603 break;
604
605 default:
606 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
607 return false;
608 }
609
610 return true;
611}
612
613template <typename ParamType>
614bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
615{
616 switch (ConvertToGLenum(params[0]))
617 {
618 case GL_NEAREST:
619 case GL_LINEAR:
620 break;
621
622 default:
623 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
624 return false;
625 }
626
627 return true;
628}
629
630template <typename ParamType>
631bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
632{
633 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
634 switch (ConvertToGLenum(params[0]))
635 {
636 case GL_NONE:
637 case GL_COMPARE_REF_TO_TEXTURE:
638 break;
639
640 default:
641 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
642 return false;
643 }
644
645 return true;
646}
647
648template <typename ParamType>
649bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
650{
651 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
652 switch (ConvertToGLenum(params[0]))
653 {
654 case GL_LEQUAL:
655 case GL_GEQUAL:
656 case GL_LESS:
657 case GL_GREATER:
658 case GL_EQUAL:
659 case GL_NOTEQUAL:
660 case GL_ALWAYS:
661 case GL_NEVER:
662 break;
663
664 default:
665 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
666 return false;
667 }
668
669 return true;
670}
671
672template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700673bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
674{
675 if (!context->getExtensions().textureSRGBDecode)
676 {
677 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
678 return false;
679 }
680
681 switch (ConvertToGLenum(params[0]))
682 {
683 case GL_DECODE_EXT:
684 case GL_SKIP_DECODE_EXT:
685 break;
686
687 default:
688 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
689 return false;
690 }
691
692 return true;
693}
694
695template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400696bool ValidateTexParameterBase(Context *context,
697 GLenum target,
698 GLenum pname,
699 GLsizei bufSize,
700 ParamType *params)
701{
702 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
703 {
704 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
705 return false;
706 }
707
708 if (context->getTargetTexture(target) == nullptr)
709 {
710 // Should only be possible for external textures
711 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
712 return false;
713 }
714
715 const GLsizei minBufSize = 1;
716 if (bufSize >= 0 && bufSize < minBufSize)
717 {
718 context->handleError(
719 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
720 return false;
721 }
722
723 switch (pname)
724 {
725 case GL_TEXTURE_WRAP_R:
726 case GL_TEXTURE_SWIZZLE_R:
727 case GL_TEXTURE_SWIZZLE_G:
728 case GL_TEXTURE_SWIZZLE_B:
729 case GL_TEXTURE_SWIZZLE_A:
730 case GL_TEXTURE_BASE_LEVEL:
731 case GL_TEXTURE_MAX_LEVEL:
732 case GL_TEXTURE_COMPARE_MODE:
733 case GL_TEXTURE_COMPARE_FUNC:
734 case GL_TEXTURE_MIN_LOD:
735 case GL_TEXTURE_MAX_LOD:
736 if (context->getClientMajorVersion() < 3)
737 {
738 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
739 return false;
740 }
741 if (target == GL_TEXTURE_EXTERNAL_OES &&
742 !context->getExtensions().eglImageExternalEssl3)
743 {
744 context->handleError(Error(GL_INVALID_ENUM,
745 "ES3 texture parameters are not available without "
746 "GL_OES_EGL_image_external_essl3."));
747 return false;
748 }
749 break;
750
751 default:
752 break;
753 }
754
755 switch (pname)
756 {
757 case GL_TEXTURE_WRAP_S:
758 case GL_TEXTURE_WRAP_T:
759 case GL_TEXTURE_WRAP_R:
760 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
761 {
762 return false;
763 }
764 break;
765
766 case GL_TEXTURE_MIN_FILTER:
767 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
768 {
769 return false;
770 }
771 break;
772
773 case GL_TEXTURE_MAG_FILTER:
774 if (!ValidateTextureMagFilterValue(context, params))
775 {
776 return false;
777 }
778 break;
779
780 case GL_TEXTURE_USAGE_ANGLE:
781 switch (ConvertToGLenum(params[0]))
782 {
783 case GL_NONE:
784 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
785 break;
786
787 default:
788 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
789 return false;
790 }
791 break;
792
793 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
794 if (!context->getExtensions().textureFilterAnisotropic)
795 {
796 context->handleError(
797 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
798 return false;
799 }
800
801 // we assume the parameter passed to this validation method is truncated, not rounded
802 if (params[0] < 1)
803 {
804 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
805 return false;
806 }
807 break;
808
809 case GL_TEXTURE_MIN_LOD:
810 case GL_TEXTURE_MAX_LOD:
811 // any value is permissible
812 break;
813
814 case GL_TEXTURE_COMPARE_MODE:
815 if (!ValidateTextureCompareModeValue(context, params))
816 {
817 return false;
818 }
819 break;
820
821 case GL_TEXTURE_COMPARE_FUNC:
822 if (!ValidateTextureCompareFuncValue(context, params))
823 {
824 return false;
825 }
826 break;
827
828 case GL_TEXTURE_SWIZZLE_R:
829 case GL_TEXTURE_SWIZZLE_G:
830 case GL_TEXTURE_SWIZZLE_B:
831 case GL_TEXTURE_SWIZZLE_A:
832 switch (ConvertToGLenum(params[0]))
833 {
834 case GL_RED:
835 case GL_GREEN:
836 case GL_BLUE:
837 case GL_ALPHA:
838 case GL_ZERO:
839 case GL_ONE:
840 break;
841
842 default:
843 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
844 return false;
845 }
846 break;
847
848 case GL_TEXTURE_BASE_LEVEL:
849 if (params[0] < 0)
850 {
851 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
852 return false;
853 }
854 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
855 {
856 context->handleError(
857 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
858 return false;
859 }
860 break;
861
862 case GL_TEXTURE_MAX_LEVEL:
863 if (params[0] < 0)
864 {
865 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
866 return false;
867 }
868 break;
869
Geoff Lang3b573612016-10-31 14:08:10 -0400870 case GL_DEPTH_STENCIL_TEXTURE_MODE:
871 if (context->getClientVersion() < Version(3, 1))
872 {
873 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
874 return false;
875 }
Geoff Lang9f090372016-12-02 10:20:43 -0500876 switch (ConvertToGLenum(params[0]))
877 {
878 case GL_DEPTH_COMPONENT:
879 case GL_STENCIL_INDEX:
880 break;
881
882 default:
883 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
884 return false;
885 }
Geoff Lang3b573612016-10-31 14:08:10 -0400886 break;
887
Geoff Lang81c6b572016-10-19 14:07:52 -0700888 case GL_TEXTURE_SRGB_DECODE_EXT:
889 if (!ValidateTextureSRGBDecodeValue(context, params))
890 {
891 return false;
892 }
893 break;
894
Geoff Langc1984ed2016-10-07 12:41:00 -0400895 default:
896 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
897 return false;
898 }
899
900 return true;
901}
902
903template <typename ParamType>
904bool ValidateSamplerParameterBase(Context *context,
905 GLuint sampler,
906 GLenum pname,
907 GLsizei bufSize,
908 ParamType *params)
909{
910 if (context->getClientMajorVersion() < 3)
911 {
912 context->handleError(
913 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
914 return false;
915 }
916
917 if (!context->isSampler(sampler))
918 {
919 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
920 return false;
921 }
922
923 const GLsizei minBufSize = 1;
924 if (bufSize >= 0 && bufSize < minBufSize)
925 {
926 context->handleError(
927 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
928 return false;
929 }
930
931 switch (pname)
932 {
933 case GL_TEXTURE_WRAP_S:
934 case GL_TEXTURE_WRAP_T:
935 case GL_TEXTURE_WRAP_R:
936 if (!ValidateTextureWrapModeValue(context, params, false))
937 {
938 return false;
939 }
940 break;
941
942 case GL_TEXTURE_MIN_FILTER:
943 if (!ValidateTextureMinFilterValue(context, params, false))
944 {
945 return false;
946 }
947 break;
948
949 case GL_TEXTURE_MAG_FILTER:
950 if (!ValidateTextureMagFilterValue(context, params))
951 {
952 return false;
953 }
954 break;
955
956 case GL_TEXTURE_MIN_LOD:
957 case GL_TEXTURE_MAX_LOD:
958 // any value is permissible
959 break;
960
961 case GL_TEXTURE_COMPARE_MODE:
962 if (!ValidateTextureCompareModeValue(context, params))
963 {
964 return false;
965 }
966 break;
967
968 case GL_TEXTURE_COMPARE_FUNC:
969 if (!ValidateTextureCompareFuncValue(context, params))
970 {
971 return false;
972 }
973 break;
974
Geoff Lang81c6b572016-10-19 14:07:52 -0700975 case GL_TEXTURE_SRGB_DECODE_EXT:
976 if (!ValidateTextureSRGBDecodeValue(context, params))
977 {
978 return false;
979 }
980 break;
981
Geoff Langc1984ed2016-10-07 12:41:00 -0400982 default:
983 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
984 return false;
985 }
986
987 return true;
988}
989
990bool ValidateGetSamplerParameterBase(Context *context,
991 GLuint sampler,
992 GLenum pname,
993 GLsizei *length)
994{
995 if (length)
996 {
997 *length = 0;
998 }
999
1000 if (context->getClientMajorVersion() < 3)
1001 {
1002 context->handleError(
1003 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1004 return false;
1005 }
1006
1007 if (!context->isSampler(sampler))
1008 {
1009 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
1010 return false;
1011 }
1012
1013 switch (pname)
1014 {
1015 case GL_TEXTURE_WRAP_S:
1016 case GL_TEXTURE_WRAP_T:
1017 case GL_TEXTURE_WRAP_R:
1018 case GL_TEXTURE_MIN_FILTER:
1019 case GL_TEXTURE_MAG_FILTER:
1020 case GL_TEXTURE_MIN_LOD:
1021 case GL_TEXTURE_MAX_LOD:
1022 case GL_TEXTURE_COMPARE_MODE:
1023 case GL_TEXTURE_COMPARE_FUNC:
1024 break;
1025
Geoff Lang81c6b572016-10-19 14:07:52 -07001026 case GL_TEXTURE_SRGB_DECODE_EXT:
1027 if (!context->getExtensions().textureSRGBDecode)
1028 {
1029 context->handleError(
1030 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
1031 return false;
1032 }
1033 break;
1034
Geoff Langc1984ed2016-10-07 12:41:00 -04001035 default:
1036 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1037 return false;
1038 }
1039
1040 if (length)
1041 {
1042 *length = 1;
1043 }
1044 return true;
1045}
1046
Geoff Lang0b031062016-10-13 14:30:04 -04001047bool ValidateGetVertexAttribBase(Context *context,
1048 GLuint index,
1049 GLenum pname,
1050 GLsizei *length,
1051 bool pointer,
1052 bool pureIntegerEntryPoint)
1053{
1054 if (length)
1055 {
1056 *length = 0;
1057 }
1058
1059 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1060 {
1061 context->handleError(
1062 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1063 return false;
1064 }
1065
1066 if (index >= context->getCaps().maxVertexAttributes)
1067 {
1068 context->handleError(Error(
1069 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1070 return false;
1071 }
1072
1073 if (pointer)
1074 {
1075 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1076 {
1077 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1078 return false;
1079 }
1080 }
1081 else
1082 {
1083 switch (pname)
1084 {
1085 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1086 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1087 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1088 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1089 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1090 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1091 case GL_CURRENT_VERTEX_ATTRIB:
1092 break;
1093
1094 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1095 static_assert(
1096 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1097 "ANGLE extension enums not equal to GL enums.");
1098 if (context->getClientMajorVersion() < 3 &&
1099 !context->getExtensions().instancedArrays)
1100 {
1101 context->handleError(Error(GL_INVALID_ENUM,
1102 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1103 "3.0 or GL_ANGLE_instanced_arrays."));
1104 return false;
1105 }
1106 break;
1107
1108 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1109 if (context->getClientMajorVersion() < 3)
1110 {
1111 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1112 return false;
1113 }
1114 break;
1115
1116 default:
1117 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1118 return false;
1119 }
1120 }
1121
1122 if (length)
1123 {
1124 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1125 {
1126 *length = 4;
1127 }
1128 else
1129 {
1130 *length = 1;
1131 }
1132 }
1133
1134 return true;
1135}
1136
Geoff Lang6899b872016-10-14 11:30:13 -04001137bool ValidateGetActiveUniformBlockivBase(Context *context,
1138 GLuint program,
1139 GLuint uniformBlockIndex,
1140 GLenum pname,
1141 GLsizei *length)
1142{
1143 if (length)
1144 {
1145 *length = 0;
1146 }
1147
1148 if (context->getClientMajorVersion() < 3)
1149 {
1150 context->handleError(
1151 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1152 return false;
1153 }
1154
1155 Program *programObject = GetValidProgram(context, program);
1156 if (!programObject)
1157 {
1158 return false;
1159 }
1160
1161 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1162 {
1163 context->handleError(
1164 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1165 return false;
1166 }
1167
1168 switch (pname)
1169 {
1170 case GL_UNIFORM_BLOCK_BINDING:
1171 case GL_UNIFORM_BLOCK_DATA_SIZE:
1172 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1173 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1174 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1175 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1176 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1177 break;
1178
1179 default:
1180 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1181 return false;
1182 }
1183
1184 if (length)
1185 {
1186 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1187 {
1188 const UniformBlock &uniformBlock =
1189 programObject->getUniformBlockByIndex(uniformBlockIndex);
1190 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1191 }
1192 else
1193 {
1194 *length = 1;
1195 }
1196 }
1197
1198 return true;
1199}
1200
Geoff Langebebe1c2016-10-14 12:01:31 -04001201bool ValidateGetBufferParameterBase(ValidationContext *context,
1202 GLenum target,
1203 GLenum pname,
1204 bool pointerVersion,
1205 GLsizei *numParams)
1206{
1207 if (numParams)
1208 {
1209 *numParams = 0;
1210 }
1211
1212 if (!ValidBufferTarget(context, target))
1213 {
1214 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1215 return false;
1216 }
1217
1218 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1219 if (!buffer)
1220 {
1221 // A null buffer means that "0" is bound to the requested buffer target
1222 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1223 return false;
1224 }
1225
1226 const Extensions &extensions = context->getExtensions();
1227
1228 switch (pname)
1229 {
1230 case GL_BUFFER_USAGE:
1231 case GL_BUFFER_SIZE:
1232 break;
1233
1234 case GL_BUFFER_ACCESS_OES:
1235 if (!extensions.mapBuffer)
1236 {
1237 context->handleError(
Jamie Madillcc6ac252017-01-25 12:57:21 -08001238 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001239 return false;
1240 }
1241 break;
1242
1243 case GL_BUFFER_MAPPED:
1244 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1245 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1246 !extensions.mapBufferRange)
1247 {
1248 context->handleError(Error(
1249 GL_INVALID_ENUM,
Jamie Madillcc6ac252017-01-25 12:57:21 -08001250 "pname requires OpenGL ES 3.0, GL_OES_mapbuffer or GL_EXT_map_buffer_range."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001251 return false;
1252 }
1253 break;
1254
1255 case GL_BUFFER_MAP_POINTER:
1256 if (!pointerVersion)
1257 {
1258 context->handleError(
1259 Error(GL_INVALID_ENUM,
1260 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1261 return false;
1262 }
1263 break;
1264
1265 case GL_BUFFER_ACCESS_FLAGS:
1266 case GL_BUFFER_MAP_OFFSET:
1267 case GL_BUFFER_MAP_LENGTH:
1268 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1269 {
1270 context->handleError(Error(
1271 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1272 return false;
1273 }
1274 break;
1275
1276 default:
1277 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1278 return false;
1279 }
1280
1281 // All buffer parameter queries return one value.
1282 if (numParams)
1283 {
1284 *numParams = 1;
1285 }
1286
1287 return true;
1288}
1289
Geoff Lang0a9661f2016-10-20 10:59:20 -07001290bool ValidateGetInternalFormativBase(Context *context,
1291 GLenum target,
1292 GLenum internalformat,
1293 GLenum pname,
1294 GLsizei bufSize,
1295 GLsizei *numParams)
1296{
1297 if (numParams)
1298 {
1299 *numParams = 0;
1300 }
1301
1302 if (context->getClientMajorVersion() < 3)
1303 {
1304 context->handleError(
1305 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1306 return false;
1307 }
1308
1309 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1310 if (!formatCaps.renderable)
1311 {
1312 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1313 return false;
1314 }
1315
1316 switch (target)
1317 {
1318 case GL_RENDERBUFFER:
1319 break;
1320
JiangYizhoubddc46b2016-12-09 09:50:51 +08001321 case GL_TEXTURE_2D_MULTISAMPLE:
1322 if (context->getClientVersion() < ES_3_1)
1323 {
1324 context->handleError(
1325 Error(GL_INVALID_OPERATION, "Texture target requires at least OpenGL ES 3.1."));
1326 return false;
1327 }
1328 break;
1329
Geoff Lang0a9661f2016-10-20 10:59:20 -07001330 default:
1331 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1332 return false;
1333 }
1334
1335 if (bufSize < 0)
1336 {
1337 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1338 return false;
1339 }
1340
1341 GLsizei maxWriteParams = 0;
1342 switch (pname)
1343 {
1344 case GL_NUM_SAMPLE_COUNTS:
1345 maxWriteParams = 1;
1346 break;
1347
1348 case GL_SAMPLES:
1349 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1350 break;
1351
1352 default:
1353 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1354 return false;
1355 }
1356
1357 if (numParams)
1358 {
1359 // glGetInternalFormativ will not overflow bufSize
1360 *numParams = std::min(bufSize, maxWriteParams);
1361 }
1362
1363 return true;
1364}
1365
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001366bool ValidateUniformCommonBase(gl::Context *context,
1367 gl::Program *program,
1368 GLint location,
1369 GLsizei count,
1370 const LinkedUniform **uniformOut)
1371{
1372 // TODO(Jiajia): Add image uniform check in future.
1373 if (count < 0)
1374 {
1375 context->handleError(Error(GL_INVALID_VALUE));
1376 return false;
1377 }
1378
1379 if (!program || !program->isLinked())
1380 {
1381 context->handleError(Error(GL_INVALID_OPERATION));
1382 return false;
1383 }
1384
1385 if (location == -1)
1386 {
1387 // Silently ignore the uniform command
1388 return false;
1389 }
1390
1391 const auto &uniformLocations = program->getUniformLocations();
1392 size_t castedLocation = static_cast<size_t>(location);
1393 if (castedLocation >= uniformLocations.size())
1394 {
1395 context->handleError(Error(GL_INVALID_OPERATION, "Invalid uniform location"));
1396 return false;
1397 }
1398
1399 const auto &uniformLocation = uniformLocations[castedLocation];
1400 if (uniformLocation.ignored)
1401 {
1402 // Silently ignore the uniform command
1403 return false;
1404 }
1405
1406 if (!uniformLocation.used)
1407 {
1408 context->handleError(Error(GL_INVALID_OPERATION));
1409 return false;
1410 }
1411
1412 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
1413
1414 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
1415 if (!uniform.isArray() && count > 1)
1416 {
1417 context->handleError(Error(GL_INVALID_OPERATION));
1418 return false;
1419 }
1420
1421 *uniformOut = &uniform;
1422 return true;
1423}
1424
Frank Henigman999b0fd2017-02-02 21:45:55 -05001425bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -05001426 GLenum uniformType,
1427 GLsizei count,
1428 const GLint *value)
1429{
1430 // Value type is GL_INT, because we only get here from glUniform1i{v}.
1431 // It is compatible with INT or BOOL.
1432 // Do these cheap tests first, for a little extra speed.
1433 if (GL_INT == uniformType || GL_BOOL == uniformType)
1434 {
1435 return true;
1436 }
1437
1438 if (IsSamplerType(uniformType))
1439 {
Frank Henigman999b0fd2017-02-02 21:45:55 -05001440 // Check that the values are in range.
1441 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
1442 for (GLsizei i = 0; i < count; ++i)
1443 {
1444 if (value[i] < 0 || value[i] >= max)
1445 {
1446 context->handleError(Error(GL_INVALID_VALUE, "sampler uniform value out of range"));
1447 return false;
1448 }
1449 }
Frank Henigmana98a6472017-02-02 21:38:32 -05001450 return true;
1451 }
1452
1453 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1454 return false;
1455}
1456
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001457bool ValidateUniformValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1458{
1459 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -05001460 // Do the cheaper test first, for a little extra speed.
1461 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001462 {
1463 return true;
1464 }
1465
1466 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1467 return false;
1468}
1469
1470bool ValidateUniformMatrixValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1471{
1472 // Check that the value type is compatible with uniform type.
1473 if (valueType == uniformType)
1474 {
1475 return true;
1476 }
1477
1478 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1479 return false;
1480}
1481
Geoff Langf41a7152016-09-19 15:11:17 -04001482} // anonymous namespace
1483
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001484bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001485{
Jamie Madilld7460c72014-01-21 16:38:14 -05001486 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001487 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001488 case GL_TEXTURE_2D:
1489 case GL_TEXTURE_CUBE_MAP:
1490 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001491
He Yunchaoced53ae2016-11-29 15:00:51 +08001492 case GL_TEXTURE_3D:
1493 case GL_TEXTURE_2D_ARRAY:
1494 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001495
He Yunchaoced53ae2016-11-29 15:00:51 +08001496 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001497 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001498
He Yunchaoced53ae2016-11-29 15:00:51 +08001499 default:
1500 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001501 }
Jamie Madill35d15012013-10-07 10:46:37 -04001502}
1503
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001504bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1505{
1506 switch (target)
1507 {
1508 case GL_TEXTURE_2D:
1509 case GL_TEXTURE_CUBE_MAP:
1510 return true;
1511
1512 default:
1513 return false;
1514 }
1515}
1516
1517bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1518{
1519 switch (target)
1520 {
1521 case GL_TEXTURE_3D:
1522 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001523 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001524
1525 default:
1526 return false;
1527 }
1528}
1529
Ian Ewellbda75592016-04-18 17:25:54 -04001530// Most texture GL calls are not compatible with external textures, so we have a separate validation
1531// function for use in the GL calls that do
1532bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1533{
1534 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1535 (context->getExtensions().eglImageExternal ||
1536 context->getExtensions().eglStreamConsumerExternal);
1537}
1538
Shannon Woods4dfed832014-03-17 20:03:39 -04001539// This function differs from ValidTextureTarget in that the target must be
1540// usable as the destination of a 2D operation-- so a cube face is valid, but
1541// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001542// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001543bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001544{
1545 switch (target)
1546 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001547 case GL_TEXTURE_2D:
1548 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1549 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1550 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1551 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1552 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1553 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1554 return true;
1555 default:
1556 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001557 }
1558}
1559
1560bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1561{
1562 switch (target)
1563 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001564 case GL_TEXTURE_3D:
1565 case GL_TEXTURE_2D_ARRAY:
1566 return true;
1567 default:
1568 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001569 }
1570}
1571
He Yunchao11b038b2016-11-22 21:24:04 +08001572bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1573{
1574 switch (target)
1575 {
1576 case GL_TEXTURE_2D:
1577 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1578 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1579 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1580 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1581 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1582 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1583 case GL_TEXTURE_3D:
1584 case GL_TEXTURE_2D_ARRAY:
1585 case GL_TEXTURE_2D_MULTISAMPLE:
1586 return true;
1587 default:
1588 return false;
1589 }
1590}
1591
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001592bool ValidFramebufferTarget(GLenum target)
1593{
He Yunchaoced53ae2016-11-29 15:00:51 +08001594 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1595 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001596 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001597
1598 switch (target)
1599 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001600 case GL_FRAMEBUFFER:
1601 return true;
1602 case GL_READ_FRAMEBUFFER:
1603 return true;
1604 case GL_DRAW_FRAMEBUFFER:
1605 return true;
1606 default:
1607 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001608 }
1609}
1610
Jamie Madill29639852016-09-02 15:00:09 -04001611bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001612{
1613 switch (target)
1614 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001615 case GL_ARRAY_BUFFER:
1616 case GL_ELEMENT_ARRAY_BUFFER:
1617 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001618
He Yunchaoced53ae2016-11-29 15:00:51 +08001619 case GL_PIXEL_PACK_BUFFER:
1620 case GL_PIXEL_UNPACK_BUFFER:
1621 return (context->getExtensions().pixelBufferObject ||
1622 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001623
He Yunchaoced53ae2016-11-29 15:00:51 +08001624 case GL_COPY_READ_BUFFER:
1625 case GL_COPY_WRITE_BUFFER:
1626 case GL_TRANSFORM_FEEDBACK_BUFFER:
1627 case GL_UNIFORM_BUFFER:
1628 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001629
He Yunchaoced53ae2016-11-29 15:00:51 +08001630 case GL_ATOMIC_COUNTER_BUFFER:
1631 case GL_SHADER_STORAGE_BUFFER:
1632 case GL_DRAW_INDIRECT_BUFFER:
1633 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001634 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001635
He Yunchaoced53ae2016-11-29 15:00:51 +08001636 default:
1637 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001638 }
1639}
1640
Jamie Madillc29968b2016-01-20 11:17:23 -05001641bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001642{
Jamie Madillc29968b2016-01-20 11:17:23 -05001643 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001644 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001645 switch (target)
1646 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001647 case GL_TEXTURE_2D:
1648 maxDimension = caps.max2DTextureSize;
1649 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001650 case GL_TEXTURE_CUBE_MAP:
1651 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1652 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1653 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1654 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1655 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1656 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1657 maxDimension = caps.maxCubeMapTextureSize;
1658 break;
1659 case GL_TEXTURE_3D:
1660 maxDimension = caps.max3DTextureSize;
1661 break;
1662 case GL_TEXTURE_2D_ARRAY:
1663 maxDimension = caps.max2DTextureSize;
1664 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001665 case GL_TEXTURE_2D_MULTISAMPLE:
1666 maxDimension = caps.max2DTextureSize;
1667 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001668 default:
1669 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001670 }
1671
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001672 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001673}
1674
Geoff Langcc507aa2016-12-12 10:09:52 -05001675bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001676 GLenum target,
1677 GLint level,
1678 GLsizei width,
1679 GLsizei height,
1680 GLsizei depth,
1681 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001682{
1683 if (level < 0 || width < 0 || height < 0 || depth < 0)
1684 {
1685 return false;
1686 }
1687
Austin Kinross08528e12015-10-07 16:24:40 -07001688 // TexSubImage parameters can be NPOT without textureNPOT extension,
1689 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001690 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001691 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001692 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001693 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001694 {
1695 return false;
1696 }
1697
1698 if (!ValidMipLevel(context, target, level))
1699 {
1700 return false;
1701 }
1702
1703 return true;
1704}
1705
Geoff Lang0d8b7242015-09-09 14:56:53 -04001706bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1707{
1708 // List of compressed format that require that the texture size is smaller than or a multiple of
1709 // the compressed block size.
1710 switch (internalFormat)
1711 {
1712 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1713 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1714 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1715 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001716 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001717 return true;
1718
1719 default:
1720 return false;
1721 }
1722}
1723
Jamie Madillc29968b2016-01-20 11:17:23 -05001724bool ValidCompressedImageSize(const ValidationContext *context,
1725 GLenum internalFormat,
Geoff Lang44ff5a72017-02-03 15:15:43 -05001726 GLint xoffset,
1727 GLint yoffset,
Jamie Madillc29968b2016-01-20 11:17:23 -05001728 GLsizei width,
1729 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001730{
Geoff Lang5d601382014-07-22 15:14:06 -04001731 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1732 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001733 {
1734 return false;
1735 }
1736
Geoff Lang44ff5a72017-02-03 15:15:43 -05001737 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001738 {
1739 return false;
1740 }
1741
Geoff Lang0d8b7242015-09-09 14:56:53 -04001742 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1743 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001744 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
1745 yoffset % formatInfo.compressedBlockHeight != 0 ||
1746 (static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
Geoff Lang0d8b7242015-09-09 14:56:53 -04001747 width % formatInfo.compressedBlockWidth != 0) ||
1748 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1749 height % formatInfo.compressedBlockHeight != 0))
1750 {
1751 return false;
1752 }
1753 }
1754
Geoff Langd4f180b2013-09-24 13:57:44 -04001755 return true;
1756}
1757
Geoff Langff5b2d52016-09-07 11:32:23 -04001758bool ValidImageDataSize(ValidationContext *context,
1759 GLenum textureTarget,
1760 GLsizei width,
1761 GLsizei height,
1762 GLsizei depth,
1763 GLenum internalFormat,
1764 GLenum type,
1765 const GLvoid *pixels,
1766 GLsizei imageSize)
1767{
1768 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1769 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1770 {
1771 // Checks are not required
1772 return true;
1773 }
1774
1775 // ...the data would be unpacked from the buffer object such that the memory reads required
1776 // would exceed the data store size.
1777 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1778 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1779 const gl::Extents size(width, height, depth);
1780 const auto &unpack = context->getGLState().getUnpackState();
1781
1782 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1783 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1784 if (endByteOrErr.isError())
1785 {
1786 context->handleError(endByteOrErr.getError());
1787 return false;
1788 }
1789
1790 GLuint endByte = endByteOrErr.getResult();
1791
1792 if (pixelUnpackBuffer)
1793 {
1794 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1795 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1796 checkedEndByte += checkedOffset;
1797
1798 if (!checkedEndByte.IsValid() ||
1799 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1800 {
1801 // Overflow past the end of the buffer
1802 context->handleError(Error(GL_INVALID_OPERATION));
1803 return false;
1804 }
1805 }
1806 else
1807 {
1808 ASSERT(imageSize >= 0);
1809 if (pixels == nullptr && imageSize != 0)
1810 {
1811 context->handleError(
1812 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001813 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001814 }
1815
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001816 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001817 {
1818 context->handleError(
1819 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1820 return false;
1821 }
1822 }
1823
1824 return true;
1825}
1826
Geoff Lang37dde692014-01-31 16:34:54 -05001827bool ValidQueryType(const Context *context, GLenum queryType)
1828{
He Yunchaoced53ae2016-11-29 15:00:51 +08001829 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1830 "GL extension enums not equal.");
1831 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1832 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001833
1834 switch (queryType)
1835 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001836 case GL_ANY_SAMPLES_PASSED:
1837 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1838 return true;
1839 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1840 return (context->getClientMajorVersion() >= 3);
1841 case GL_TIME_ELAPSED_EXT:
1842 return context->getExtensions().disjointTimerQuery;
1843 case GL_COMMANDS_COMPLETED_CHROMIUM:
1844 return context->getExtensions().syncQuery;
1845 default:
1846 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001847 }
1848}
1849
Jamie Madillef300b12016-10-07 15:12:09 -04001850Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001851{
He Yunchaoced53ae2016-11-29 15:00:51 +08001852 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1853 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1854 // or program object and INVALID_OPERATION if the provided name identifies an object
1855 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001856
Dian Xiang769769a2015-09-09 15:20:08 -07001857 Program *validProgram = context->getProgram(id);
1858
1859 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001860 {
Dian Xiang769769a2015-09-09 15:20:08 -07001861 if (context->getShader(id))
1862 {
Jamie Madill437fa652016-05-03 15:13:24 -04001863 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001864 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1865 }
1866 else
1867 {
Jamie Madill437fa652016-05-03 15:13:24 -04001868 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001869 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001870 }
Dian Xiang769769a2015-09-09 15:20:08 -07001871
1872 return validProgram;
1873}
1874
Jamie Madillef300b12016-10-07 15:12:09 -04001875Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001876{
1877 // See ValidProgram for spec details.
1878
1879 Shader *validShader = context->getShader(id);
1880
1881 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001882 {
Dian Xiang769769a2015-09-09 15:20:08 -07001883 if (context->getProgram(id))
1884 {
Jamie Madill437fa652016-05-03 15:13:24 -04001885 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001886 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1887 }
1888 else
1889 {
Jamie Madill437fa652016-05-03 15:13:24 -04001890 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001891 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001892 }
Dian Xiang769769a2015-09-09 15:20:08 -07001893
1894 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001895}
1896
Geoff Langb1196682014-07-23 13:47:29 -04001897bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001898{
1899 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1900 {
1901 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1902
Geoff Langaae65a42014-05-26 12:43:44 -04001903 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001904 {
Jamie Madill437fa652016-05-03 15:13:24 -04001905 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001906 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001907 }
1908 }
1909 else
1910 {
1911 switch (attachment)
1912 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001913 case GL_DEPTH_ATTACHMENT:
1914 case GL_STENCIL_ATTACHMENT:
1915 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001916
He Yunchaoced53ae2016-11-29 15:00:51 +08001917 case GL_DEPTH_STENCIL_ATTACHMENT:
1918 if (!context->getExtensions().webglCompatibility &&
1919 context->getClientMajorVersion() < 3)
1920 {
1921 context->handleError(Error(GL_INVALID_ENUM));
1922 return false;
1923 }
1924 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001925
He Yunchaoced53ae2016-11-29 15:00:51 +08001926 default:
1927 context->handleError(Error(GL_INVALID_ENUM));
1928 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001929 }
1930 }
1931
1932 return true;
1933}
1934
Jamie Madille8fb6402017-02-14 17:56:40 -05001935bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001936 GLenum target,
1937 GLsizei samples,
1938 GLenum internalformat,
1939 GLsizei width,
1940 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001941{
1942 switch (target)
1943 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001944 case GL_RENDERBUFFER:
1945 break;
1946 default:
1947 context->handleError(Error(GL_INVALID_ENUM));
1948 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001949 }
1950
1951 if (width < 0 || height < 0 || samples < 0)
1952 {
Jamie Madill437fa652016-05-03 15:13:24 -04001953 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001954 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001955 }
1956
Geoff Langd87878e2014-09-19 15:42:59 -04001957 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1958 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001959 {
Jamie Madill437fa652016-05-03 15:13:24 -04001960 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001961 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001962 }
1963
1964 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1965 // 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 -08001966 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001967 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001968 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001969 {
Jamie Madill437fa652016-05-03 15:13:24 -04001970 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001971 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001972 }
1973
Geoff Langaae65a42014-05-26 12:43:44 -04001974 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001975 {
Jamie Madill437fa652016-05-03 15:13:24 -04001976 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001977 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001978 }
1979
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001980 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001981 if (handle == 0)
1982 {
Jamie Madill437fa652016-05-03 15:13:24 -04001983 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001984 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001985 }
1986
1987 return true;
1988}
1989
He Yunchaoced53ae2016-11-29 15:00:51 +08001990bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1991 GLenum target,
1992 GLenum attachment,
1993 GLenum renderbuffertarget,
1994 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001995{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001996 if (!ValidFramebufferTarget(target))
1997 {
Jamie Madill437fa652016-05-03 15:13:24 -04001998 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001999 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04002000 }
2001
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002002 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002003
Jamie Madill84115c92015-04-23 15:00:07 -04002004 ASSERT(framebuffer);
2005 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002006 {
Jamie Madill437fa652016-05-03 15:13:24 -04002007 context->handleError(
2008 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002009 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002010 }
2011
Jamie Madillb4472272014-07-03 10:38:55 -04002012 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002013 {
Jamie Madillb4472272014-07-03 10:38:55 -04002014 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002015 }
2016
Jamie Madillab9d82c2014-01-21 16:38:14 -05002017 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2018 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2019 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2020 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2021 if (renderbuffer != 0)
2022 {
2023 if (!context->getRenderbuffer(renderbuffer))
2024 {
Jamie Madill437fa652016-05-03 15:13:24 -04002025 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002026 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05002027 }
2028 }
2029
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002030 return true;
2031}
2032
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002033bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002034 GLint srcX0,
2035 GLint srcY0,
2036 GLint srcX1,
2037 GLint srcY1,
2038 GLint dstX0,
2039 GLint dstY0,
2040 GLint dstX1,
2041 GLint dstY1,
2042 GLbitfield mask,
2043 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002044{
2045 switch (filter)
2046 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002047 case GL_NEAREST:
2048 break;
2049 case GL_LINEAR:
2050 break;
2051 default:
2052 context->handleError(Error(GL_INVALID_ENUM));
2053 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002054 }
2055
2056 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
2057 {
Jamie Madill437fa652016-05-03 15:13:24 -04002058 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002059 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002060 }
2061
2062 if (mask == 0)
2063 {
2064 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
2065 // buffers are copied.
2066 return false;
2067 }
2068
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002069 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
2070 // color buffer, leaving only nearest being unfiltered from above
2071 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
2072 {
Jamie Madill437fa652016-05-03 15:13:24 -04002073 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002074 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002075 }
2076
Jamie Madill51f40ec2016-06-15 14:06:00 -04002077 const auto &glState = context->getGLState();
2078 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2079 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05002080
2081 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002082 {
Jamie Madill437fa652016-05-03 15:13:24 -04002083 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002084 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002085 }
2086
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002087 if (readFramebuffer->id() == drawFramebuffer->id())
2088 {
2089 context->handleError(Error(GL_INVALID_OPERATION));
2090 return false;
2091 }
2092
Jamie Madill51f40ec2016-06-15 14:06:00 -04002093 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002094 {
Jamie Madill437fa652016-05-03 15:13:24 -04002095 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002096 return false;
2097 }
2098
Jamie Madill51f40ec2016-06-15 14:06:00 -04002099 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002100 {
Jamie Madill437fa652016-05-03 15:13:24 -04002101 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002102 return false;
2103 }
2104
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002105 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002106 {
Jamie Madill437fa652016-05-03 15:13:24 -04002107 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002108 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002109 }
2110
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002111 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2112
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002113 if (mask & GL_COLOR_BUFFER_BIT)
2114 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002115 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002116 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002117
He Yunchao66a41a22016-12-15 16:45:05 +08002118 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002119 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002120 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002121
Geoff Langa15472a2015-08-11 11:48:03 -04002122 for (size_t drawbufferIdx = 0;
2123 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002124 {
Geoff Langa15472a2015-08-11 11:48:03 -04002125 const FramebufferAttachment *attachment =
2126 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2127 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002128 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002129 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002130
Geoff Langb2f3d052013-08-13 12:49:27 -04002131 // The GL ES 3.0.2 spec (pg 193) states that:
2132 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002133 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2134 // as well
2135 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2136 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002137 // Changes with EXT_color_buffer_float:
2138 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002139 GLenum readComponentType = readFormat.info->componentType;
2140 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002141 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002142 readComponentType == GL_SIGNED_NORMALIZED);
2143 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2144 drawComponentType == GL_SIGNED_NORMALIZED);
2145
2146 if (extensions.colorBufferFloat)
2147 {
2148 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2149 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2150
2151 if (readFixedOrFloat != drawFixedOrFloat)
2152 {
Jamie Madill437fa652016-05-03 15:13:24 -04002153 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002154 "If the read buffer contains fixed-point or "
2155 "floating-point values, the draw buffer "
2156 "must as well."));
2157 return false;
2158 }
2159 }
2160 else if (readFixedPoint != drawFixedPoint)
2161 {
Jamie Madill437fa652016-05-03 15:13:24 -04002162 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002163 "If the read buffer contains fixed-point "
2164 "values, the draw buffer must as well."));
2165 return false;
2166 }
2167
2168 if (readComponentType == GL_UNSIGNED_INT &&
2169 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002170 {
Jamie Madill437fa652016-05-03 15:13:24 -04002171 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002172 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002173 }
2174
Jamie Madill6163c752015-12-07 16:32:59 -05002175 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002176 {
Jamie Madill437fa652016-05-03 15:13:24 -04002177 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002178 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002179 }
2180
Jamie Madilla3944d42016-07-22 22:13:26 -04002181 if (readColorBuffer->getSamples() > 0 &&
2182 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002183 {
Jamie Madill437fa652016-05-03 15:13:24 -04002184 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002185 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002186 }
2187 }
2188 }
2189
Jamie Madilla3944d42016-07-22 22:13:26 -04002190 if ((readFormat.info->componentType == GL_INT ||
2191 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2192 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002193 {
Jamie Madill437fa652016-05-03 15:13:24 -04002194 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002195 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002196 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002197 }
He Yunchao66a41a22016-12-15 16:45:05 +08002198 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2199 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2200 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2201 // situation is an application error that would lead to a crash in ANGLE.
2202 else if (drawFramebuffer->hasEnabledDrawBuffer())
2203 {
2204 context->handleError(Error(
2205 GL_INVALID_OPERATION,
2206 "Attempt to read from a missing color attachment of a complete framebuffer."));
2207 return false;
2208 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002209 }
2210
He Yunchaoced53ae2016-11-29 15:00:51 +08002211 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002212 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2213 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002214 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002215 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002216 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002217 const gl::FramebufferAttachment *readBuffer =
2218 readFramebuffer->getAttachment(attachments[i]);
2219 const gl::FramebufferAttachment *drawBuffer =
2220 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002221
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002222 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002223 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002224 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002225 {
Jamie Madill437fa652016-05-03 15:13:24 -04002226 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002227 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002228 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002229
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002230 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002231 {
Jamie Madill437fa652016-05-03 15:13:24 -04002232 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002233 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002234 }
2235 }
He Yunchao66a41a22016-12-15 16:45:05 +08002236 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2237 else if (drawBuffer)
2238 {
2239 context->handleError(Error(GL_INVALID_OPERATION,
2240 "Attempt to read from a missing depth/stencil "
2241 "attachment of a complete framebuffer."));
2242 return false;
2243 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002244 }
2245 }
2246
2247 return true;
2248}
2249
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002250bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002251 GLint x,
2252 GLint y,
2253 GLsizei width,
2254 GLsizei height,
2255 GLenum format,
2256 GLenum type,
2257 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002258{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002259 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2260}
2261
2262bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2263 GLint x,
2264 GLint y,
2265 GLsizei width,
2266 GLsizei height,
2267 GLenum format,
2268 GLenum type,
2269 GLsizei bufSize,
2270 GLsizei *length,
2271 GLvoid *pixels)
2272{
2273 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002274 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002275 return false;
2276 }
2277
Geoff Lang62fce5b2016-09-30 10:46:35 -04002278 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2279 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002280 {
Geoff Langb1196682014-07-23 13:47:29 -04002281 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002282 }
2283
Geoff Lang62fce5b2016-09-30 10:46:35 -04002284 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002285 {
Geoff Langb1196682014-07-23 13:47:29 -04002286 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002287 }
2288
Jamie Madillc29968b2016-01-20 11:17:23 -05002289 return true;
2290}
2291
2292bool ValidateReadnPixelsEXT(Context *context,
2293 GLint x,
2294 GLint y,
2295 GLsizei width,
2296 GLsizei height,
2297 GLenum format,
2298 GLenum type,
2299 GLsizei bufSize,
2300 GLvoid *pixels)
2301{
2302 if (bufSize < 0)
2303 {
Jamie Madill437fa652016-05-03 15:13:24 -04002304 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002305 return false;
2306 }
2307
Geoff Lang62fce5b2016-09-30 10:46:35 -04002308 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2309 pixels);
2310}
Jamie Madill26e91952014-03-05 15:01:27 -05002311
Geoff Lang62fce5b2016-09-30 10:46:35 -04002312bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2313 GLint x,
2314 GLint y,
2315 GLsizei width,
2316 GLsizei height,
2317 GLenum format,
2318 GLenum type,
2319 GLsizei bufSize,
2320 GLsizei *length,
2321 GLvoid *data)
2322{
2323 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002324 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002325 return false;
2326 }
2327
Geoff Lang62fce5b2016-09-30 10:46:35 -04002328 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002329 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002330 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002331 }
2332
Geoff Lang62fce5b2016-09-30 10:46:35 -04002333 if (!ValidateRobustBufferSize(context, bufSize, *length))
2334 {
2335 return false;
2336 }
2337
2338 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002339}
2340
Olli Etuaho41997e72016-03-10 13:38:39 +02002341bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002342{
2343 if (!context->getExtensions().occlusionQueryBoolean &&
2344 !context->getExtensions().disjointTimerQuery)
2345 {
Jamie Madill437fa652016-05-03 15:13:24 -04002346 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002347 return false;
2348 }
2349
Olli Etuaho41997e72016-03-10 13:38:39 +02002350 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002351}
2352
Olli Etuaho41997e72016-03-10 13:38:39 +02002353bool ValidateDeleteQueriesEXT(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
2365bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002366{
2367 if (!ValidQueryType(context, target))
2368 {
Jamie Madill437fa652016-05-03 15:13:24 -04002369 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002370 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002371 }
2372
2373 if (id == 0)
2374 {
Jamie Madill437fa652016-05-03 15:13:24 -04002375 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002376 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002377 }
2378
2379 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2380 // of zero, if the active query object name for <target> is non-zero (for the
2381 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2382 // the active query for either target is non-zero), if <id> is the name of an
2383 // existing query object whose type does not match <target>, or if <id> is the
2384 // active query object name for any query type, the error INVALID_OPERATION is
2385 // generated.
2386
2387 // Ensure no other queries are active
2388 // NOTE: If other queries than occlusion are supported, we will need to check
2389 // separately that:
2390 // a) The query ID passed is not the current active query for any target/type
2391 // b) There are no active queries for the requested target (and in the case
2392 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2393 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002394
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002395 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002396 {
Jamie Madill437fa652016-05-03 15:13:24 -04002397 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002398 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002399 }
2400
2401 Query *queryObject = context->getQuery(id, true, target);
2402
2403 // check that name was obtained with glGenQueries
2404 if (!queryObject)
2405 {
Jamie Madill437fa652016-05-03 15:13:24 -04002406 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002407 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002408 }
2409
2410 // check for type mismatch
2411 if (queryObject->getType() != target)
2412 {
Jamie Madill437fa652016-05-03 15:13:24 -04002413 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002414 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002415 }
2416
2417 return true;
2418}
2419
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002420bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2421{
2422 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002423 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002424 {
Jamie Madill437fa652016-05-03 15:13:24 -04002425 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002426 return false;
2427 }
2428
2429 return ValidateBeginQueryBase(context, target, id);
2430}
2431
2432bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002433{
2434 if (!ValidQueryType(context, target))
2435 {
Jamie Madill437fa652016-05-03 15:13:24 -04002436 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002437 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002438 }
2439
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002440 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002441
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002442 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002443 {
Jamie Madill437fa652016-05-03 15:13:24 -04002444 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002445 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002446 }
2447
Jamie Madill45c785d2014-05-13 14:09:34 -04002448 return true;
2449}
2450
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002451bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2452{
2453 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002454 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002455 {
Jamie Madill437fa652016-05-03 15:13:24 -04002456 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002457 return false;
2458 }
2459
2460 return ValidateEndQueryBase(context, target);
2461}
2462
2463bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2464{
2465 if (!context->getExtensions().disjointTimerQuery)
2466 {
Jamie Madill437fa652016-05-03 15:13:24 -04002467 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002468 return false;
2469 }
2470
2471 if (target != GL_TIMESTAMP_EXT)
2472 {
Jamie Madill437fa652016-05-03 15:13:24 -04002473 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002474 return false;
2475 }
2476
2477 Query *queryObject = context->getQuery(id, true, target);
2478 if (queryObject == nullptr)
2479 {
Jamie Madill437fa652016-05-03 15:13:24 -04002480 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002481 return false;
2482 }
2483
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002484 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002485 {
Jamie Madill437fa652016-05-03 15:13:24 -04002486 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002487 return false;
2488 }
2489
2490 return true;
2491}
2492
Geoff Lang2186c382016-10-14 10:54:54 -04002493bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002494{
Geoff Lang2186c382016-10-14 10:54:54 -04002495 if (numParams)
2496 {
2497 *numParams = 0;
2498 }
2499
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002500 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2501 {
Jamie Madill437fa652016-05-03 15:13:24 -04002502 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002503 return false;
2504 }
2505
2506 switch (pname)
2507 {
2508 case GL_CURRENT_QUERY_EXT:
2509 if (target == GL_TIMESTAMP_EXT)
2510 {
Jamie Madill437fa652016-05-03 15:13:24 -04002511 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002512 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2513 return false;
2514 }
2515 break;
2516 case GL_QUERY_COUNTER_BITS_EXT:
2517 if (!context->getExtensions().disjointTimerQuery ||
2518 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2519 {
Jamie Madill437fa652016-05-03 15:13:24 -04002520 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002521 return false;
2522 }
2523 break;
2524 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002525 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002526 return false;
2527 }
2528
Geoff Lang2186c382016-10-14 10:54:54 -04002529 if (numParams)
2530 {
2531 // All queries return only one value
2532 *numParams = 1;
2533 }
2534
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002535 return true;
2536}
2537
2538bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2539{
2540 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002541 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002542 {
Jamie Madill437fa652016-05-03 15:13:24 -04002543 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002544 return false;
2545 }
2546
Geoff Lang2186c382016-10-14 10:54:54 -04002547 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002548}
2549
Geoff Lang2186c382016-10-14 10:54:54 -04002550bool ValidateGetQueryivRobustANGLE(Context *context,
2551 GLenum target,
2552 GLenum pname,
2553 GLsizei bufSize,
2554 GLsizei *length,
2555 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002556{
Geoff Lang2186c382016-10-14 10:54:54 -04002557 if (!ValidateRobustEntryPoint(context, bufSize))
2558 {
2559 return false;
2560 }
2561
2562 if (!ValidateGetQueryivBase(context, target, pname, length))
2563 {
2564 return false;
2565 }
2566
2567 if (!ValidateRobustBufferSize(context, bufSize, *length))
2568 {
2569 return false;
2570 }
2571
2572 return true;
2573}
2574
2575bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2576{
2577 if (numParams)
2578 {
2579 *numParams = 0;
2580 }
2581
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002582 Query *queryObject = context->getQuery(id, false, GL_NONE);
2583
2584 if (!queryObject)
2585 {
Jamie Madill437fa652016-05-03 15:13:24 -04002586 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002587 return false;
2588 }
2589
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002590 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002591 {
Jamie Madill437fa652016-05-03 15:13:24 -04002592 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002593 return false;
2594 }
2595
2596 switch (pname)
2597 {
2598 case GL_QUERY_RESULT_EXT:
2599 case GL_QUERY_RESULT_AVAILABLE_EXT:
2600 break;
2601
2602 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002603 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002604 return false;
2605 }
2606
Geoff Lang2186c382016-10-14 10:54:54 -04002607 if (numParams)
2608 {
2609 *numParams = 1;
2610 }
2611
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002612 return true;
2613}
2614
2615bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2616{
2617 if (!context->getExtensions().disjointTimerQuery)
2618 {
Jamie Madill437fa652016-05-03 15:13:24 -04002619 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002620 return false;
2621 }
Geoff Lang2186c382016-10-14 10:54:54 -04002622 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2623}
2624
2625bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2626 GLuint id,
2627 GLenum pname,
2628 GLsizei bufSize,
2629 GLsizei *length,
2630 GLint *params)
2631{
2632 if (!context->getExtensions().disjointTimerQuery)
2633 {
2634 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2635 return false;
2636 }
2637
2638 if (!ValidateRobustEntryPoint(context, bufSize))
2639 {
2640 return false;
2641 }
2642
2643 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2644 {
2645 return false;
2646 }
2647
2648 if (!ValidateRobustBufferSize(context, bufSize, *length))
2649 {
2650 return false;
2651 }
2652
2653 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002654}
2655
2656bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2657{
2658 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002659 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002660 {
Jamie Madill437fa652016-05-03 15:13:24 -04002661 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002662 return false;
2663 }
Geoff Lang2186c382016-10-14 10:54:54 -04002664 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2665}
2666
2667bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2668 GLuint id,
2669 GLenum pname,
2670 GLsizei bufSize,
2671 GLsizei *length,
2672 GLuint *params)
2673{
2674 if (!context->getExtensions().disjointTimerQuery &&
2675 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2676 {
2677 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2678 return false;
2679 }
2680
2681 if (!ValidateRobustEntryPoint(context, bufSize))
2682 {
2683 return false;
2684 }
2685
2686 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2687 {
2688 return false;
2689 }
2690
2691 if (!ValidateRobustBufferSize(context, bufSize, *length))
2692 {
2693 return false;
2694 }
2695
2696 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002697}
2698
2699bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2700{
2701 if (!context->getExtensions().disjointTimerQuery)
2702 {
Jamie Madill437fa652016-05-03 15:13:24 -04002703 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002704 return false;
2705 }
Geoff Lang2186c382016-10-14 10:54:54 -04002706 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2707}
2708
2709bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2710 GLuint id,
2711 GLenum pname,
2712 GLsizei bufSize,
2713 GLsizei *length,
2714 GLint64 *params)
2715{
2716 if (!context->getExtensions().disjointTimerQuery)
2717 {
2718 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2719 return false;
2720 }
2721
2722 if (!ValidateRobustEntryPoint(context, bufSize))
2723 {
2724 return false;
2725 }
2726
2727 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2728 {
2729 return false;
2730 }
2731
2732 if (!ValidateRobustBufferSize(context, bufSize, *length))
2733 {
2734 return false;
2735 }
2736
2737 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002738}
2739
2740bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2741{
2742 if (!context->getExtensions().disjointTimerQuery)
2743 {
Jamie Madill437fa652016-05-03 15:13:24 -04002744 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002745 return false;
2746 }
Geoff Lang2186c382016-10-14 10:54:54 -04002747 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2748}
2749
2750bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2751 GLuint id,
2752 GLenum pname,
2753 GLsizei bufSize,
2754 GLsizei *length,
2755 GLuint64 *params)
2756{
2757 if (!context->getExtensions().disjointTimerQuery)
2758 {
2759 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2760 return false;
2761 }
2762
2763 if (!ValidateRobustEntryPoint(context, bufSize))
2764 {
2765 return false;
2766 }
2767
2768 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2769 {
2770 return false;
2771 }
2772
2773 if (!ValidateRobustBufferSize(context, bufSize, *length))
2774 {
2775 return false;
2776 }
2777
2778 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002779}
2780
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002781bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002782 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002783 GLuint program,
2784 GLint location,
2785 GLsizei count)
2786{
2787 // Check for ES31 program uniform entry points
2788 if (context->getClientVersion() < Version(3, 1))
2789 {
2790 context->handleError(Error(GL_INVALID_OPERATION));
2791 return false;
2792 }
2793
2794 const LinkedUniform *uniform = nullptr;
2795 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002796 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2797 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002798}
2799
Frank Henigmana98a6472017-02-02 21:38:32 -05002800bool ValidateProgramUniform1iv(gl::Context *context,
2801 GLuint program,
2802 GLint location,
2803 GLsizei count,
2804 const GLint *value)
2805{
2806 // Check for ES31 program uniform entry points
2807 if (context->getClientVersion() < Version(3, 1))
2808 {
2809 context->handleError(Error(GL_INVALID_OPERATION));
2810 return false;
2811 }
2812
2813 const LinkedUniform *uniform = nullptr;
2814 gl::Program *programObject = GetValidProgram(context, program);
2815 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2816 ValidateUniform1ivValue(context, uniform->type, count, value);
2817}
2818
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002819bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002820 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002821 GLuint program,
2822 GLint location,
2823 GLsizei count,
2824 GLboolean transpose)
2825{
2826 // Check for ES31 program uniform entry points
2827 if (context->getClientVersion() < Version(3, 1))
2828 {
2829 context->handleError(Error(GL_INVALID_OPERATION));
2830 return false;
2831 }
2832
2833 const LinkedUniform *uniform = nullptr;
2834 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002835 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2836 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002837}
2838
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002839bool ValidateUniform(gl::Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002840{
2841 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002842 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002843 {
Jamie Madill437fa652016-05-03 15:13:24 -04002844 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002845 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002846 }
2847
Jamie Madill62d31cb2015-09-11 13:25:51 -04002848 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002849 gl::Program *programObject = context->getGLState().getProgram();
2850 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2851 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002852}
2853
Frank Henigmana98a6472017-02-02 21:38:32 -05002854bool ValidateUniform1iv(gl::Context *context, GLint location, GLsizei count, const GLint *value)
2855{
2856 const LinkedUniform *uniform = nullptr;
2857 gl::Program *programObject = context->getGLState().getProgram();
2858 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2859 ValidateUniform1ivValue(context, uniform->type, count, value);
2860}
2861
He Yunchaoced53ae2016-11-29 15:00:51 +08002862bool ValidateUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002863 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002864 GLint location,
2865 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002866 GLboolean transpose)
2867{
2868 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002869 int rows = VariableRowCount(valueType);
2870 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002871 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002872 {
Jamie Madill437fa652016-05-03 15:13:24 -04002873 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002874 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002875 }
2876
Martin Radev1be913c2016-07-11 17:59:16 +03002877 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002878 {
Jamie Madill437fa652016-05-03 15:13:24 -04002879 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002880 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002881 }
2882
Jamie Madill62d31cb2015-09-11 13:25:51 -04002883 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002884 gl::Program *programObject = context->getGLState().getProgram();
2885 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2886 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002887}
2888
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002889bool ValidateStateQuery(ValidationContext *context,
2890 GLenum pname,
2891 GLenum *nativeType,
2892 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002893{
2894 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2895 {
Jamie Madill437fa652016-05-03 15:13:24 -04002896 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002897 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002898 }
2899
Jamie Madill0af26e12015-03-05 19:54:33 -05002900 const Caps &caps = context->getCaps();
2901
Jamie Madill893ab082014-05-16 16:56:10 -04002902 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2903 {
2904 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2905
Jamie Madill0af26e12015-03-05 19:54:33 -05002906 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002907 {
Jamie Madill437fa652016-05-03 15:13:24 -04002908 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002909 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002910 }
2911 }
2912
2913 switch (pname)
2914 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002915 case GL_TEXTURE_BINDING_2D:
2916 case GL_TEXTURE_BINDING_CUBE_MAP:
2917 case GL_TEXTURE_BINDING_3D:
2918 case GL_TEXTURE_BINDING_2D_ARRAY:
2919 break;
2920 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2921 if (!context->getExtensions().eglStreamConsumerExternal &&
2922 !context->getExtensions().eglImageExternal)
2923 {
2924 context->handleError(Error(GL_INVALID_ENUM,
2925 "Neither NV_EGL_stream_consumer_external nor "
2926 "GL_OES_EGL_image_external extensions enabled"));
2927 return false;
2928 }
2929 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002930
He Yunchaoced53ae2016-11-29 15:00:51 +08002931 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2932 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002933 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002934 if (context->getGLState().getReadFramebuffer()->checkStatus(
2935 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002936 {
Jamie Madill437fa652016-05-03 15:13:24 -04002937 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002938 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002939 }
2940
Jamie Madill51f40ec2016-06-15 14:06:00 -04002941 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2942 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002943
2944 if (framebuffer->getReadBufferState() == GL_NONE)
2945 {
2946 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2947 return false;
2948 }
2949
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002950 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002951 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002952 {
Jamie Madill437fa652016-05-03 15:13:24 -04002953 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002954 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002955 }
2956 }
2957 break;
2958
He Yunchaoced53ae2016-11-29 15:00:51 +08002959 default:
2960 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002961 }
2962
2963 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002964 if (*numParams == 0)
2965 {
2966 return false;
2967 }
2968
2969 return true;
2970}
2971
2972bool ValidateRobustStateQuery(ValidationContext *context,
2973 GLenum pname,
2974 GLsizei bufSize,
2975 GLenum *nativeType,
2976 unsigned int *numParams)
2977{
2978 if (!ValidateRobustEntryPoint(context, bufSize))
2979 {
2980 return false;
2981 }
2982
2983 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2984 {
2985 return false;
2986 }
2987
2988 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002989 {
2990 return false;
2991 }
2992
2993 return true;
2994}
2995
Jamie Madillc29968b2016-01-20 11:17:23 -05002996bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2997 GLenum target,
2998 GLint level,
2999 GLenum internalformat,
3000 bool isSubImage,
3001 GLint xoffset,
3002 GLint yoffset,
3003 GLint zoffset,
3004 GLint x,
3005 GLint y,
3006 GLsizei width,
3007 GLsizei height,
3008 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04003009 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04003010{
Jamie Madill560a8d82014-05-21 13:06:20 -04003011 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
3012 {
Jamie Madill437fa652016-05-03 15:13:24 -04003013 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003014 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003015 }
3016
He Yunchaoced53ae2016-11-29 15:00:51 +08003017 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3018 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04003019 {
Jamie Madill437fa652016-05-03 15:13:24 -04003020 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003021 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003022 }
3023
3024 if (border != 0)
3025 {
Jamie Madill437fa652016-05-03 15:13:24 -04003026 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003027 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003028 }
3029
3030 if (!ValidMipLevel(context, target, level))
3031 {
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
Jamie Madill51f40ec2016-06-15 14:06:00 -04003036 const auto &state = context->getGLState();
3037 auto readFramebuffer = state.getReadFramebuffer();
3038 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003039 {
Jamie Madill437fa652016-05-03 15:13:24 -04003040 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003041 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003042 }
3043
Jamie Madill51f40ec2016-06-15 14:06:00 -04003044 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003045 {
Jamie Madill437fa652016-05-03 15:13:24 -04003046 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003047 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003048 }
3049
Martin Radev138064f2016-07-15 12:03:41 +03003050 if (readFramebuffer->getReadBufferState() == GL_NONE)
3051 {
3052 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3053 return false;
3054 }
3055
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003056 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3057 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003058 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003059 // situation is an application error that would lead to a crash in ANGLE.
3060 if (readFramebuffer->getReadColorbuffer() == nullptr)
3061 {
3062 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3063 return false;
3064 }
3065
Geoff Langaae65a42014-05-26 12:43:44 -04003066 const gl::Caps &caps = context->getCaps();
3067
Geoff Langaae65a42014-05-26 12:43:44 -04003068 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003069 switch (target)
3070 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003071 case GL_TEXTURE_2D:
3072 maxDimension = caps.max2DTextureSize;
3073 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003074
He Yunchaoced53ae2016-11-29 15:00:51 +08003075 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3076 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3077 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3078 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3079 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3080 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3081 maxDimension = caps.maxCubeMapTextureSize;
3082 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003083
He Yunchaoced53ae2016-11-29 15:00:51 +08003084 case GL_TEXTURE_2D_ARRAY:
3085 maxDimension = caps.max2DTextureSize;
3086 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003087
He Yunchaoced53ae2016-11-29 15:00:51 +08003088 case GL_TEXTURE_3D:
3089 maxDimension = caps.max3DTextureSize;
3090 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003091
He Yunchaoced53ae2016-11-29 15:00:51 +08003092 default:
3093 context->handleError(Error(GL_INVALID_ENUM));
3094 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003095 }
3096
Jamie Madillc29968b2016-01-20 11:17:23 -05003097 gl::Texture *texture =
3098 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003099 if (!texture)
3100 {
Jamie Madill437fa652016-05-03 15:13:24 -04003101 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003102 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003103 }
3104
Geoff Lang69cce582015-09-17 13:20:36 -04003105 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003106 {
Jamie Madill437fa652016-05-03 15:13:24 -04003107 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003108 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003109 }
3110
Geoff Lang5d601382014-07-22 15:14:06 -04003111 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3112
3113 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003114 {
Jamie Madill437fa652016-05-03 15:13:24 -04003115 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003116 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003117 }
3118
Geoff Lang44ff5a72017-02-03 15:15:43 -05003119 if (formatInfo.compressed &&
3120 !ValidCompressedImageSize(context, internalformat, xoffset, yoffset, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003121 {
Jamie Madill437fa652016-05-03 15:13:24 -04003122 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003123 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003124 }
3125
3126 if (isSubImage)
3127 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003128 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3129 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3130 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003131 {
Jamie Madill437fa652016-05-03 15:13:24 -04003132 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003133 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003134 }
3135 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003136 else
3137 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003138 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003139 {
Jamie Madill437fa652016-05-03 15:13:24 -04003140 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003141 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003142 }
3143
Geoff Langeb66a6e2016-10-31 13:06:12 -04003144 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003145 {
Jamie Madill437fa652016-05-03 15:13:24 -04003146 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003147 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003148 }
3149
3150 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003151 if (static_cast<int>(width) > maxLevelDimension ||
3152 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003153 {
Jamie Madill437fa652016-05-03 15:13:24 -04003154 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003155 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003156 }
3157 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003158
Jamie Madill0c8abca2016-07-22 20:21:26 -04003159 if (textureFormatOut)
3160 {
3161 *textureFormatOut = texture->getFormat(target, level);
3162 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003163
3164 // Detect texture copying feedback loops for WebGL.
3165 if (context->getExtensions().webglCompatibility)
3166 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05003167 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05003168 {
3169 context->handleError(Error(GL_INVALID_OPERATION,
3170 "Texture copying feedback loop formed between Framebuffer "
3171 "and specified Texture level."));
3172 return false;
3173 }
3174 }
3175
Jamie Madill560a8d82014-05-21 13:06:20 -04003176 return true;
3177}
3178
Jiajia Qind9671222016-11-29 16:30:31 +08003179bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003180{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003181 switch (mode)
3182 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003183 case GL_POINTS:
3184 case GL_LINES:
3185 case GL_LINE_LOOP:
3186 case GL_LINE_STRIP:
3187 case GL_TRIANGLES:
3188 case GL_TRIANGLE_STRIP:
3189 case GL_TRIANGLE_FAN:
3190 break;
3191 default:
3192 context->handleError(Error(GL_INVALID_ENUM));
3193 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003194 }
3195
Jamie Madill250d33f2014-06-06 17:09:03 -04003196 if (count < 0)
3197 {
Jamie Madill437fa652016-05-03 15:13:24 -04003198 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003199 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003200 }
3201
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003202 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003203
Jamie Madill250d33f2014-06-06 17:09:03 -04003204 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003205 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003206 {
Jamie Madill437fa652016-05-03 15:13:24 -04003207 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003208 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003209 }
3210
Jamie Madillcbcde722017-01-06 14:50:00 -05003211 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3212 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003213 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003214 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3215 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003216 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003217 const FramebufferAttachment *dsAttachment =
3218 framebuffer->getStencilOrDepthStencilAttachment();
3219 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003220 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003221 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003222
3223 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3224 bool differentWritemasks =
3225 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3226 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3227 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3228 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3229
3230 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003231 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003232 if (!context->getExtensions().webglCompatibility)
3233 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003234 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3235 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003236 }
Jamie Madill437fa652016-05-03 15:13:24 -04003237 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003238 return false;
3239 }
Jamie Madillac528012014-06-20 13:21:23 -04003240 }
3241
Jamie Madill51f40ec2016-06-15 14:06:00 -04003242 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003243 {
Jamie Madill437fa652016-05-03 15:13:24 -04003244 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003245 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003246 }
3247
Geoff Lang7dd2e102014-11-10 15:19:26 -05003248 gl::Program *program = state.getProgram();
3249 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003250 {
Jamie Madill437fa652016-05-03 15:13:24 -04003251 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003252 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003253 }
3254
Geoff Lang7dd2e102014-11-10 15:19:26 -05003255 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003256 {
Jamie Madill437fa652016-05-03 15:13:24 -04003257 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003258 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003259 }
3260
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003261 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003262 for (unsigned int uniformBlockIndex = 0;
3263 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003264 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003265 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003266 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003267 const OffsetBindingPointer<Buffer> &uniformBuffer =
3268 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003269
Geoff Lang5d124a62015-09-15 13:03:27 -04003270 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003271 {
3272 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003273 context->handleError(
3274 Error(GL_INVALID_OPERATION,
3275 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003276 return false;
3277 }
3278
Geoff Lang5d124a62015-09-15 13:03:27 -04003279 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003280 if (uniformBufferSize == 0)
3281 {
3282 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003283 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003284 }
3285
Jamie Madill62d31cb2015-09-11 13:25:51 -04003286 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003287 {
3288 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003289 context->handleError(
3290 Error(GL_INVALID_OPERATION,
3291 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003292 return false;
3293 }
3294 }
3295
Jamie Madilla4595b82017-01-11 17:36:34 -05003296 // Detect rendering feedback loops for WebGL.
3297 if (context->getExtensions().webglCompatibility)
3298 {
3299 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3300 {
3301 context->handleError(
3302 Error(GL_INVALID_OPERATION,
3303 "Rendering feedback loop formed between Framebuffer and active Texture."));
3304 return false;
3305 }
3306 }
3307
Jamie Madill250d33f2014-06-06 17:09:03 -04003308 // No-op if zero count
3309 return (count > 0);
3310}
3311
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003312bool ValidateDrawArrays(ValidationContext *context,
3313 GLenum mode,
3314 GLint first,
3315 GLsizei count,
3316 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003317{
Jamie Madillfd716582014-06-06 17:09:04 -04003318 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003319 {
Jamie Madill437fa652016-05-03 15:13:24 -04003320 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003321 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003322 }
3323
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003324 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003325 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003326 if (curTransformFeedback && curTransformFeedback->isActive() &&
3327 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003328 {
3329 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003330 // that does not match the current transform feedback object's draw mode (if transform
3331 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003332 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003333 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003334 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003335 }
3336
Jiajia Qind9671222016-11-29 16:30:31 +08003337 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003338 {
3339 return false;
3340 }
3341
Corentin Wallez71168a02016-12-19 15:11:18 -08003342 // Check the computation of maxVertex doesn't overflow.
3343 // - first < 0 or count < 0 have been checked as an error condition
3344 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3345 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3346 ASSERT(count > 0 && first >= 0);
3347 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3348 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003349 {
3350 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3351 return false;
3352 }
3353
Corentin Wallez71168a02016-12-19 15:11:18 -08003354 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003355 {
3356 return false;
3357 }
3358
3359 return true;
3360}
3361
He Yunchaoced53ae2016-11-29 15:00:51 +08003362bool ValidateDrawArraysInstanced(Context *context,
3363 GLenum mode,
3364 GLint first,
3365 GLsizei count,
3366 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003367{
3368 if (primcount < 0)
3369 {
Jamie Madill437fa652016-05-03 15:13:24 -04003370 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003371 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003372 }
3373
Jamie Madill2b976812014-08-25 15:47:49 -04003374 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003375 {
3376 return false;
3377 }
3378
3379 // No-op if zero primitive count
3380 return (primcount > 0);
3381}
3382
Geoff Lang87a93302014-09-16 13:29:43 -04003383static bool ValidateDrawInstancedANGLE(Context *context)
3384{
3385 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003386 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003387
Geoff Lang7dd2e102014-11-10 15:19:26 -05003388 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003389
Jiawei-Shao2597fb62016-12-09 16:38:02 +08003390 const auto &attribs = state.getVertexArray()->getVertexAttributes();
3391 const auto &bindings = state.getVertexArray()->getVertexBindings();
Jamie Madill63805b42015-08-25 13:17:39 -04003392 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003393 {
Jiawei-Shao2597fb62016-12-09 16:38:02 +08003394 const VertexAttribute &attrib = attribs[attributeIndex];
3395 const VertexBinding &binding = bindings[attrib.bindingIndex];
3396 if (program->isAttribLocationActive(attributeIndex) && binding.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003397 {
3398 return true;
3399 }
3400 }
3401
Jamie Madill437fa652016-05-03 15:13:24 -04003402 context->handleError(Error(GL_INVALID_OPERATION,
3403 "ANGLE_instanced_arrays requires that at least one active attribute"
3404 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003405 return false;
3406}
3407
He Yunchaoced53ae2016-11-29 15:00:51 +08003408bool ValidateDrawArraysInstancedANGLE(Context *context,
3409 GLenum mode,
3410 GLint first,
3411 GLsizei count,
3412 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003413{
3414 if (!ValidateDrawInstancedANGLE(context))
3415 {
3416 return false;
3417 }
3418
3419 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3420}
3421
Jiajia Qind9671222016-11-29 16:30:31 +08003422bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003423{
Jamie Madill250d33f2014-06-06 17:09:03 -04003424 switch (type)
3425 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003426 case GL_UNSIGNED_BYTE:
3427 case GL_UNSIGNED_SHORT:
3428 break;
3429 case GL_UNSIGNED_INT:
3430 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3431 {
3432 context->handleError(Error(GL_INVALID_ENUM));
3433 return false;
3434 }
3435 break;
3436 default:
3437 context->handleError(Error(GL_INVALID_ENUM));
3438 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003439 }
3440
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003441 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003442
3443 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003444 if (curTransformFeedback && curTransformFeedback->isActive() &&
3445 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003446 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003447 // It is an invalid operation to call DrawElements, DrawRangeElements or
3448 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003449 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003450 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003451 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003452 }
3453
Jiajia Qind9671222016-11-29 16:30:31 +08003454 return true;
3455}
3456
3457bool ValidateDrawElements(ValidationContext *context,
3458 GLenum mode,
3459 GLsizei count,
3460 GLenum type,
3461 const GLvoid *indices,
3462 GLsizei primcount,
3463 IndexRange *indexRangeOut)
3464{
3465 if (!ValidateDrawElementsBase(context, type))
3466 return false;
3467
3468 const State &state = context->getGLState();
3469
Jamie Madill250d33f2014-06-06 17:09:03 -04003470 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003471 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003472 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003473 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04003474 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003475 }
3476
He Yunchaoced53ae2016-11-29 15:00:51 +08003477 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003478 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003479
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003480 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3481
3482 if (context->getExtensions().webglCompatibility)
3483 {
3484 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3485 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3486 {
3487 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3488 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3489 // data type passed to the call, or an INVALID_OPERATION error is generated.
3490 context->handleError(Error(GL_INVALID_OPERATION,
3491 "indices must be a multiple of the element type size."));
3492 return false;
3493 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003494 }
3495
3496 if (context->getExtensions().webglCompatibility ||
3497 !context->getGLState().areClientArraysEnabled())
3498 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003499 if (!elementArrayBuffer && count > 0)
3500 {
3501 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3502 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3503 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3504 context->handleError(Error(GL_INVALID_OPERATION,
3505 "There is no element array buffer bound and count > 0."));
3506 return false;
3507 }
3508 }
3509
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003510 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003511 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003512 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003513 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003514 GLint64 offset = reinterpret_cast<GLint64>(indices);
3515 GLint64 byteCount =
3516 static_cast<GLint64>(typeBytes) * static_cast<GLint64>(count) + offset;
3517
3518 // check for integer overflows
3519 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeBytes) ||
3520 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3521 {
3522 context->handleError(Error(GL_OUT_OF_MEMORY, "Integer overflow."));
3523 return false;
3524 }
3525
3526 // Check for reading past the end of the bound buffer object
3527 if (byteCount > elementArrayBuffer->getSize())
3528 {
3529 context->handleError(
3530 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
3531 return false;
3532 }
3533 }
3534 else if (!indices)
3535 {
3536 // This is an application error that would normally result in a crash,
3537 // but we catch it and return an error
3538 context->handleError(
3539 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003540 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003541 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003542 }
3543
Jiajia Qind9671222016-11-29 16:30:31 +08003544 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003545 {
3546 return false;
3547 }
3548
Jamie Madill2b976812014-08-25 15:47:49 -04003549 // Use max index to validate if our vertex buffers are large enough for the pull.
3550 // TODO: offer fast path, with disabled index validation.
3551 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3552 if (elementArrayBuffer)
3553 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003554 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003555 Error error =
3556 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3557 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003558 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003559 {
Jamie Madill437fa652016-05-03 15:13:24 -04003560 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003561 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003562 }
3563 }
3564 else
3565 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003566 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003567 }
3568
Jamie Madille79b1e12015-11-04 16:36:37 -05003569 // If we use an index greater than our maximum supported index range, return an error.
3570 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3571 // return an error if possible here.
3572 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3573 {
Jamie Madill437fa652016-05-03 15:13:24 -04003574 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003575 return false;
3576 }
3577
Corentin Wallez92db6942016-12-09 13:10:36 -05003578 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3579 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003580 {
3581 return false;
3582 }
3583
Geoff Lang3edfe032015-09-04 16:38:24 -04003584 // No op if there are no real indices in the index data (all are primitive restart).
3585 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003586}
3587
Geoff Langb1196682014-07-23 13:47:29 -04003588bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003589 GLenum mode,
3590 GLsizei count,
3591 GLenum type,
3592 const GLvoid *indices,
3593 GLsizei primcount,
3594 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003595{
3596 if (primcount < 0)
3597 {
Jamie Madill437fa652016-05-03 15:13:24 -04003598 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003599 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003600 }
3601
Jamie Madill2b976812014-08-25 15:47:49 -04003602 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003603 {
3604 return false;
3605 }
3606
3607 // No-op zero primitive count
3608 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003609}
3610
Geoff Lang3edfe032015-09-04 16:38:24 -04003611bool ValidateDrawElementsInstancedANGLE(Context *context,
3612 GLenum mode,
3613 GLsizei count,
3614 GLenum type,
3615 const GLvoid *indices,
3616 GLsizei primcount,
3617 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003618{
3619 if (!ValidateDrawInstancedANGLE(context))
3620 {
3621 return false;
3622 }
3623
He Yunchaoced53ae2016-11-29 15:00:51 +08003624 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3625 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003626}
3627
He Yunchaoced53ae2016-11-29 15:00:51 +08003628bool ValidateFramebufferTextureBase(Context *context,
3629 GLenum target,
3630 GLenum attachment,
3631 GLuint texture,
3632 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003633{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003634 if (!ValidFramebufferTarget(target))
3635 {
Jamie Madill437fa652016-05-03 15:13:24 -04003636 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003637 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003638 }
3639
3640 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003641 {
3642 return false;
3643 }
3644
Jamie Madill55ec3b12014-07-03 10:38:57 -04003645 if (texture != 0)
3646 {
3647 gl::Texture *tex = context->getTexture(texture);
3648
3649 if (tex == NULL)
3650 {
Jamie Madill437fa652016-05-03 15:13:24 -04003651 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003652 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003653 }
3654
3655 if (level < 0)
3656 {
Jamie Madill437fa652016-05-03 15:13:24 -04003657 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003658 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003659 }
3660 }
3661
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003662 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003663 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003664
Jamie Madill84115c92015-04-23 15:00:07 -04003665 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003666 {
Jamie Madill437fa652016-05-03 15:13:24 -04003667 context->handleError(
3668 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003669 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003670 }
3671
3672 return true;
3673}
3674
He Yunchaoced53ae2016-11-29 15:00:51 +08003675bool ValidateFramebufferTexture2D(Context *context,
3676 GLenum target,
3677 GLenum attachment,
3678 GLenum textarget,
3679 GLuint texture,
3680 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003681{
He Yunchaoced53ae2016-11-29 15:00:51 +08003682 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3683 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003684 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3685 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003686 {
Jamie Madill437fa652016-05-03 15:13:24 -04003687 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003688 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003689 }
3690
3691 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003692 {
3693 return false;
3694 }
3695
Jamie Madill55ec3b12014-07-03 10:38:57 -04003696 if (texture != 0)
3697 {
3698 gl::Texture *tex = context->getTexture(texture);
3699 ASSERT(tex);
3700
Jamie Madill2a6564e2014-07-11 09:53:19 -04003701 const gl::Caps &caps = context->getCaps();
3702
Jamie Madill55ec3b12014-07-03 10:38:57 -04003703 switch (textarget)
3704 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003705 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003706 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003707 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003708 {
Jamie Madill437fa652016-05-03 15:13:24 -04003709 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003710 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003711 }
3712 if (tex->getTarget() != GL_TEXTURE_2D)
3713 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003714 context->handleError(Error(GL_INVALID_OPERATION,
3715 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003716 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003717 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003718 }
3719 break;
3720
He Yunchaoced53ae2016-11-29 15:00:51 +08003721 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3722 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3723 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3724 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3725 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3726 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003727 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003728 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003729 {
Jamie Madill437fa652016-05-03 15:13:24 -04003730 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003731 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003732 }
3733 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3734 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003735 context->handleError(Error(GL_INVALID_OPERATION,
3736 "Textarget must match the texture target type."));
3737 return false;
3738 }
3739 }
3740 break;
3741
3742 case GL_TEXTURE_2D_MULTISAMPLE:
3743 {
3744 if (context->getClientVersion() < ES_3_1)
3745 {
3746 context->handleError(Error(GL_INVALID_OPERATION,
3747 "Texture target requires at least OpenGL ES 3.1."));
3748 return false;
3749 }
3750
3751 if (level != 0)
3752 {
3753 context->handleError(
3754 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
3755 return false;
3756 }
3757 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
3758 {
3759 context->handleError(Error(GL_INVALID_OPERATION,
3760 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003761 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003762 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003763 }
3764 break;
3765
He Yunchaoced53ae2016-11-29 15:00:51 +08003766 default:
3767 context->handleError(Error(GL_INVALID_ENUM));
3768 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003769 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003770
Jamie Madilla3944d42016-07-22 22:13:26 -04003771 const Format &format = tex->getFormat(textarget, level);
3772 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003773 {
Jamie Madill437fa652016-05-03 15:13:24 -04003774 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003775 return false;
3776 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003777 }
3778
Jamie Madill570f7c82014-07-03 10:38:54 -04003779 return true;
3780}
3781
Geoff Langb1196682014-07-23 13:47:29 -04003782bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003783{
3784 if (program == 0)
3785 {
Jamie Madill437fa652016-05-03 15:13:24 -04003786 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003787 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003788 }
3789
Dian Xiang769769a2015-09-09 15:20:08 -07003790 gl::Program *programObject = GetValidProgram(context, program);
3791 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003792 {
3793 return false;
3794 }
3795
Jamie Madill0063c512014-08-25 15:47:53 -04003796 if (!programObject || !programObject->isLinked())
3797 {
Jamie Madill437fa652016-05-03 15:13:24 -04003798 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003799 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003800 }
3801
Geoff Lang7dd2e102014-11-10 15:19:26 -05003802 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003803 {
Jamie Madill437fa652016-05-03 15:13:24 -04003804 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003805 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003806 }
3807
Jamie Madill0063c512014-08-25 15:47:53 -04003808 return true;
3809}
3810
He Yunchaoced53ae2016-11-29 15:00:51 +08003811bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003812{
3813 return ValidateGetUniformBase(context, program, location);
3814}
3815
He Yunchaoced53ae2016-11-29 15:00:51 +08003816bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003817{
Jamie Madill78f41802014-08-25 15:47:55 -04003818 return ValidateGetUniformBase(context, program, location);
3819}
3820
Geoff Langf41d0ee2016-10-07 13:04:23 -04003821static bool ValidateSizedGetUniform(Context *context,
3822 GLuint program,
3823 GLint location,
3824 GLsizei bufSize,
3825 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003826{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003827 if (length)
3828 {
3829 *length = 0;
3830 }
3831
Jamie Madill78f41802014-08-25 15:47:55 -04003832 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003833 {
Jamie Madill78f41802014-08-25 15:47:55 -04003834 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003835 }
3836
Geoff Langf41d0ee2016-10-07 13:04:23 -04003837 if (bufSize < 0)
3838 {
3839 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3840 return false;
3841 }
3842
Jamie Madilla502c742014-08-28 17:19:13 -04003843 gl::Program *programObject = context->getProgram(program);
3844 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003845
Jamie Madill78f41802014-08-25 15:47:55 -04003846 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003847 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003848 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003849 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003850 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003851 context->handleError(
3852 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003853 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003854 }
3855
Geoff Langf41d0ee2016-10-07 13:04:23 -04003856 if (length)
3857 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003858 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003859 }
3860
Jamie Madill0063c512014-08-25 15:47:53 -04003861 return true;
3862}
3863
He Yunchaoced53ae2016-11-29 15:00:51 +08003864bool ValidateGetnUniformfvEXT(Context *context,
3865 GLuint program,
3866 GLint location,
3867 GLsizei bufSize,
3868 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003869{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003870 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003871}
3872
He Yunchaoced53ae2016-11-29 15:00:51 +08003873bool ValidateGetnUniformivEXT(Context *context,
3874 GLuint program,
3875 GLint location,
3876 GLsizei bufSize,
3877 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003878{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003879 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3880}
3881
3882bool ValidateGetUniformfvRobustANGLE(Context *context,
3883 GLuint program,
3884 GLint location,
3885 GLsizei bufSize,
3886 GLsizei *length,
3887 GLfloat *params)
3888{
3889 if (!ValidateRobustEntryPoint(context, bufSize))
3890 {
3891 return false;
3892 }
3893
3894 // bufSize is validated in ValidateSizedGetUniform
3895 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3896}
3897
3898bool ValidateGetUniformivRobustANGLE(Context *context,
3899 GLuint program,
3900 GLint location,
3901 GLsizei bufSize,
3902 GLsizei *length,
3903 GLint *params)
3904{
3905 if (!ValidateRobustEntryPoint(context, bufSize))
3906 {
3907 return false;
3908 }
3909
3910 // bufSize is validated in ValidateSizedGetUniform
3911 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3912}
3913
3914bool ValidateGetUniformuivRobustANGLE(Context *context,
3915 GLuint program,
3916 GLint location,
3917 GLsizei bufSize,
3918 GLsizei *length,
3919 GLuint *params)
3920{
3921 if (!ValidateRobustEntryPoint(context, bufSize))
3922 {
3923 return false;
3924 }
3925
3926 if (context->getClientMajorVersion() < 3)
3927 {
3928 context->handleError(
3929 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3930 return false;
3931 }
3932
3933 // bufSize is validated in ValidateSizedGetUniform
3934 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003935}
3936
He Yunchaoced53ae2016-11-29 15:00:51 +08003937bool ValidateDiscardFramebufferBase(Context *context,
3938 GLenum target,
3939 GLsizei numAttachments,
3940 const GLenum *attachments,
3941 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003942{
3943 if (numAttachments < 0)
3944 {
Jamie Madill437fa652016-05-03 15:13:24 -04003945 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003946 return false;
3947 }
3948
3949 for (GLsizei i = 0; i < numAttachments; ++i)
3950 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003951 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003952 {
3953 if (defaultFramebuffer)
3954 {
Jamie Madill437fa652016-05-03 15:13:24 -04003955 context->handleError(Error(
3956 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003957 return false;
3958 }
3959
3960 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3961 {
Jamie Madill437fa652016-05-03 15:13:24 -04003962 context->handleError(Error(GL_INVALID_OPERATION,
3963 "Requested color attachment is greater than the maximum "
3964 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003965 return false;
3966 }
3967 }
3968 else
3969 {
3970 switch (attachments[i])
3971 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003972 case GL_DEPTH_ATTACHMENT:
3973 case GL_STENCIL_ATTACHMENT:
3974 case GL_DEPTH_STENCIL_ATTACHMENT:
3975 if (defaultFramebuffer)
3976 {
3977 context->handleError(
3978 Error(GL_INVALID_ENUM,
3979 "Invalid attachment when the default framebuffer is bound"));
3980 return false;
3981 }
3982 break;
3983 case GL_COLOR:
3984 case GL_DEPTH:
3985 case GL_STENCIL:
3986 if (!defaultFramebuffer)
3987 {
3988 context->handleError(
3989 Error(GL_INVALID_ENUM,
3990 "Invalid attachment when the default framebuffer is not bound"));
3991 return false;
3992 }
3993 break;
3994 default:
3995 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003996 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003997 }
3998 }
3999 }
4000
4001 return true;
4002}
4003
Austin Kinross6ee1e782015-05-29 17:05:37 -07004004bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
4005{
4006 // Note that debug marker calls must not set error state
4007
4008 if (length < 0)
4009 {
4010 return false;
4011 }
4012
4013 if (marker == nullptr)
4014 {
4015 return false;
4016 }
4017
4018 return true;
4019}
4020
4021bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
4022{
4023 // Note that debug marker calls must not set error state
4024
4025 if (length < 0)
4026 {
4027 return false;
4028 }
4029
4030 if (length > 0 && marker == nullptr)
4031 {
4032 return false;
4033 }
4034
4035 return true;
4036}
4037
Geoff Langdcab33b2015-07-21 13:03:16 -04004038bool ValidateEGLImageTargetTexture2DOES(Context *context,
4039 egl::Display *display,
4040 GLenum target,
4041 egl::Image *image)
4042{
Geoff Langa8406172015-07-21 16:53:39 -04004043 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4044 {
Jamie Madill437fa652016-05-03 15:13:24 -04004045 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004046 return false;
4047 }
4048
4049 switch (target)
4050 {
4051 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004052 if (!context->getExtensions().eglImage)
4053 {
4054 context->handleError(Error(
4055 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4056 }
4057 break;
4058
4059 case GL_TEXTURE_EXTERNAL_OES:
4060 if (!context->getExtensions().eglImageExternal)
4061 {
4062 context->handleError(Error(
4063 GL_INVALID_ENUM,
4064 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4065 }
Geoff Langa8406172015-07-21 16:53:39 -04004066 break;
4067
4068 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004069 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004070 return false;
4071 }
4072
4073 if (!display->isValidImage(image))
4074 {
Jamie Madill437fa652016-05-03 15:13:24 -04004075 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004076 return false;
4077 }
4078
4079 if (image->getSamples() > 0)
4080 {
Jamie Madill437fa652016-05-03 15:13:24 -04004081 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004082 "cannot create a 2D texture from a multisampled EGL image."));
4083 return false;
4084 }
4085
Jamie Madilla3944d42016-07-22 22:13:26 -04004086 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004087 if (!textureCaps.texturable)
4088 {
Jamie Madill437fa652016-05-03 15:13:24 -04004089 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004090 "EGL image internal format is not supported as a texture."));
4091 return false;
4092 }
4093
Geoff Langdcab33b2015-07-21 13:03:16 -04004094 return true;
4095}
4096
4097bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4098 egl::Display *display,
4099 GLenum target,
4100 egl::Image *image)
4101{
Geoff Langa8406172015-07-21 16:53:39 -04004102 if (!context->getExtensions().eglImage)
4103 {
Jamie Madill437fa652016-05-03 15:13:24 -04004104 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004105 return false;
4106 }
4107
4108 switch (target)
4109 {
4110 case GL_RENDERBUFFER:
4111 break;
4112
4113 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004114 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004115 return false;
4116 }
4117
4118 if (!display->isValidImage(image))
4119 {
Jamie Madill437fa652016-05-03 15:13:24 -04004120 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004121 return false;
4122 }
4123
Jamie Madilla3944d42016-07-22 22:13:26 -04004124 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004125 if (!textureCaps.renderable)
4126 {
Jamie Madill437fa652016-05-03 15:13:24 -04004127 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004128 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4129 return false;
4130 }
4131
Geoff Langdcab33b2015-07-21 13:03:16 -04004132 return true;
4133}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004134
4135bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4136{
Geoff Lang36167ab2015-12-07 10:27:14 -05004137 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004138 {
4139 // The default VAO should always exist
4140 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004141 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004142 return false;
4143 }
4144
4145 return true;
4146}
4147
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004148bool ValidateLinkProgram(Context *context, GLuint program)
4149{
4150 if (context->hasActiveTransformFeedback(program))
4151 {
4152 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004153 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004154 "Cannot link program while program is associated with an active "
4155 "transform feedback object."));
4156 return false;
4157 }
4158 return true;
4159}
4160
Geoff Langc5629752015-12-07 16:29:04 -05004161bool ValidateProgramBinaryBase(Context *context,
4162 GLuint program,
4163 GLenum binaryFormat,
4164 const void *binary,
4165 GLint length)
4166{
4167 Program *programObject = GetValidProgram(context, program);
4168 if (programObject == nullptr)
4169 {
4170 return false;
4171 }
4172
4173 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4174 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4175 programBinaryFormats.end())
4176 {
Jamie Madill437fa652016-05-03 15:13:24 -04004177 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004178 return false;
4179 }
4180
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004181 if (context->hasActiveTransformFeedback(program))
4182 {
4183 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004184 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004185 "Cannot change program binary while program is associated with "
4186 "an active transform feedback object."));
4187 return false;
4188 }
4189
Geoff Langc5629752015-12-07 16:29:04 -05004190 return true;
4191}
4192
4193bool ValidateGetProgramBinaryBase(Context *context,
4194 GLuint program,
4195 GLsizei bufSize,
4196 GLsizei *length,
4197 GLenum *binaryFormat,
4198 void *binary)
4199{
4200 Program *programObject = GetValidProgram(context, program);
4201 if (programObject == nullptr)
4202 {
4203 return false;
4204 }
4205
4206 if (!programObject->isLinked())
4207 {
Jamie Madill437fa652016-05-03 15:13:24 -04004208 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004209 return false;
4210 }
4211
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004212 if (context->getCaps().programBinaryFormats.empty())
4213 {
4214 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4215 return false;
4216 }
4217
Geoff Langc5629752015-12-07 16:29:04 -05004218 return true;
4219}
Jamie Madillc29968b2016-01-20 11:17:23 -05004220
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004221bool ValidateUseProgram(Context *context, GLuint program)
4222{
4223 if (program != 0)
4224 {
4225 Program *programObject = context->getProgram(program);
4226 if (!programObject)
4227 {
4228 // ES 3.1.0 section 7.3 page 72
4229 if (context->getShader(program))
4230 {
Jamie Madill437fa652016-05-03 15:13:24 -04004231 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004232 Error(GL_INVALID_OPERATION,
4233 "Attempted to use a single shader instead of a shader program."));
4234 return false;
4235 }
4236 else
4237 {
Jamie Madill437fa652016-05-03 15:13:24 -04004238 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004239 return false;
4240 }
4241 }
4242 if (!programObject->isLinked())
4243 {
Jamie Madill437fa652016-05-03 15:13:24 -04004244 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004245 return false;
4246 }
4247 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004248 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004249 {
4250 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004251 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004252 Error(GL_INVALID_OPERATION,
4253 "Cannot change active program while transform feedback is unpaused."));
4254 return false;
4255 }
4256
4257 return true;
4258}
4259
Jamie Madillc29968b2016-01-20 11:17:23 -05004260bool ValidateCopyTexImage2D(ValidationContext *context,
4261 GLenum target,
4262 GLint level,
4263 GLenum internalformat,
4264 GLint x,
4265 GLint y,
4266 GLsizei width,
4267 GLsizei height,
4268 GLint border)
4269{
Martin Radev1be913c2016-07-11 17:59:16 +03004270 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004271 {
4272 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4273 0, x, y, width, height, border);
4274 }
4275
Martin Radev1be913c2016-07-11 17:59:16 +03004276 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004277 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4278 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004279}
Jamie Madillc29968b2016-01-20 11:17:23 -05004280
4281bool ValidateFramebufferRenderbuffer(Context *context,
4282 GLenum target,
4283 GLenum attachment,
4284 GLenum renderbuffertarget,
4285 GLuint renderbuffer)
4286{
4287 if (!ValidFramebufferTarget(target) ||
4288 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4289 {
Jamie Madill437fa652016-05-03 15:13:24 -04004290 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004291 return false;
4292 }
4293
4294 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4295 renderbuffertarget, renderbuffer);
4296}
4297
4298bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4299{
4300 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4301 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4302 {
Jamie Madill437fa652016-05-03 15:13:24 -04004303 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004304 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4305 return false;
4306 }
4307
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004308 ASSERT(context->getGLState().getDrawFramebuffer());
4309 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004310 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4311
4312 // This should come first before the check for the default frame buffer
4313 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4314 // rather than INVALID_OPERATION
4315 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4316 {
4317 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4318
4319 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004320 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4321 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004322 {
4323 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004324 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4325 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4326 // 3.1 is still a bit ambiguous about the error, but future specs are
4327 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004328 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004329 return false;
4330 }
4331 else if (bufs[colorAttachment] >= maxColorAttachment)
4332 {
Jamie Madill437fa652016-05-03 15:13:24 -04004333 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004334 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004335 return false;
4336 }
4337 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4338 frameBufferId != 0)
4339 {
4340 // INVALID_OPERATION-GL is bound to buffer and ith argument
4341 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004342 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004343 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4344 return false;
4345 }
4346 }
4347
4348 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4349 // and n is not 1 or bufs is bound to value other than BACK and NONE
4350 if (frameBufferId == 0)
4351 {
4352 if (n != 1)
4353 {
Jamie Madill437fa652016-05-03 15:13:24 -04004354 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004355 "n must be 1 when GL is bound to the default framebuffer"));
4356 return false;
4357 }
4358
4359 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4360 {
Jamie Madill437fa652016-05-03 15:13:24 -04004361 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004362 GL_INVALID_OPERATION,
4363 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4364 return false;
4365 }
4366 }
4367
4368 return true;
4369}
4370
4371bool ValidateCopyTexSubImage2D(Context *context,
4372 GLenum target,
4373 GLint level,
4374 GLint xoffset,
4375 GLint yoffset,
4376 GLint x,
4377 GLint y,
4378 GLsizei width,
4379 GLsizei height)
4380{
Martin Radev1be913c2016-07-11 17:59:16 +03004381 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004382 {
4383 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4384 yoffset, x, y, width, height, 0);
4385 }
4386
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004387 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4388 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004389}
4390
Geoff Lang496c02d2016-10-20 11:38:11 -07004391bool ValidateGetBufferPointervBase(Context *context,
4392 GLenum target,
4393 GLenum pname,
4394 GLsizei *length,
4395 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004396{
Geoff Lang496c02d2016-10-20 11:38:11 -07004397 if (length)
4398 {
4399 *length = 0;
4400 }
4401
4402 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4403 {
4404 context->handleError(
4405 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004406 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004407 return false;
4408 }
4409
Olli Etuaho4f667482016-03-30 15:56:35 +03004410 if (!ValidBufferTarget(context, target))
4411 {
Jamie Madill437fa652016-05-03 15:13:24 -04004412 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004413 return false;
4414 }
4415
Geoff Lang496c02d2016-10-20 11:38:11 -07004416 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004417 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004418 case GL_BUFFER_MAP_POINTER:
4419 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004420
Geoff Lang496c02d2016-10-20 11:38:11 -07004421 default:
4422 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4423 return false;
4424 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004425
4426 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4427 // target bound to zero generate an INVALID_OPERATION error."
4428 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004429 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004430 {
Jamie Madill437fa652016-05-03 15:13:24 -04004431 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004432 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4433 return false;
4434 }
4435
Geoff Lang496c02d2016-10-20 11:38:11 -07004436 if (length)
4437 {
4438 *length = 1;
4439 }
4440
Olli Etuaho4f667482016-03-30 15:56:35 +03004441 return true;
4442}
4443
4444bool ValidateUnmapBufferBase(Context *context, GLenum target)
4445{
4446 if (!ValidBufferTarget(context, target))
4447 {
Jamie Madill437fa652016-05-03 15:13:24 -04004448 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004449 return false;
4450 }
4451
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004452 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004453
4454 if (buffer == nullptr || !buffer->isMapped())
4455 {
Jamie Madill437fa652016-05-03 15:13:24 -04004456 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004457 return false;
4458 }
4459
4460 return true;
4461}
4462
4463bool ValidateMapBufferRangeBase(Context *context,
4464 GLenum target,
4465 GLintptr offset,
4466 GLsizeiptr length,
4467 GLbitfield access)
4468{
4469 if (!ValidBufferTarget(context, target))
4470 {
Jamie Madill437fa652016-05-03 15:13:24 -04004471 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004472 return false;
4473 }
4474
4475 if (offset < 0 || length < 0)
4476 {
Jamie Madill437fa652016-05-03 15:13:24 -04004477 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004478 return false;
4479 }
4480
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004481 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004482
4483 if (!buffer)
4484 {
Jamie Madill437fa652016-05-03 15:13:24 -04004485 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004486 return false;
4487 }
4488
4489 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004490 CheckedNumeric<size_t> checkedOffset(offset);
4491 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004492
Jamie Madille2e406c2016-06-02 13:04:10 -04004493 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004494 {
Jamie Madill437fa652016-05-03 15:13:24 -04004495 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004496 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4497 return false;
4498 }
4499
4500 // Check for invalid bits in the mask
4501 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4502 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4503 GL_MAP_UNSYNCHRONIZED_BIT;
4504
4505 if (access & ~(allAccessBits))
4506 {
Jamie Madill437fa652016-05-03 15:13:24 -04004507 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004508 return false;
4509 }
4510
4511 if (length == 0)
4512 {
Jamie Madill437fa652016-05-03 15:13:24 -04004513 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004514 return false;
4515 }
4516
4517 if (buffer->isMapped())
4518 {
Jamie Madill437fa652016-05-03 15:13:24 -04004519 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004520 return false;
4521 }
4522
4523 // Check for invalid bit combinations
4524 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4525 {
Jamie Madill437fa652016-05-03 15:13:24 -04004526 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004527 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4528 return false;
4529 }
4530
4531 GLbitfield writeOnlyBits =
4532 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4533
4534 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4535 {
Jamie Madill437fa652016-05-03 15:13:24 -04004536 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004537 "Invalid access bits when mapping buffer for reading: 0x%X.",
4538 access));
4539 return false;
4540 }
4541
4542 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4543 {
Jamie Madill437fa652016-05-03 15:13:24 -04004544 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004545 GL_INVALID_OPERATION,
4546 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4547 return false;
4548 }
4549 return true;
4550}
4551
4552bool ValidateFlushMappedBufferRangeBase(Context *context,
4553 GLenum target,
4554 GLintptr offset,
4555 GLsizeiptr length)
4556{
4557 if (offset < 0 || length < 0)
4558 {
Jamie Madill437fa652016-05-03 15:13:24 -04004559 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004560 return false;
4561 }
4562
4563 if (!ValidBufferTarget(context, target))
4564 {
Jamie Madill437fa652016-05-03 15:13:24 -04004565 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004566 return false;
4567 }
4568
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004569 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004570
4571 if (buffer == nullptr)
4572 {
Jamie Madill437fa652016-05-03 15:13:24 -04004573 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004574 return false;
4575 }
4576
4577 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4578 {
Jamie Madill437fa652016-05-03 15:13:24 -04004579 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004580 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4581 return false;
4582 }
4583
4584 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004585 CheckedNumeric<size_t> checkedOffset(offset);
4586 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004587
Jamie Madille2e406c2016-06-02 13:04:10 -04004588 if (!checkedSize.IsValid() ||
4589 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004590 {
Jamie Madill437fa652016-05-03 15:13:24 -04004591 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004592 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4593 return false;
4594 }
4595
4596 return true;
4597}
4598
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004599bool ValidateGenerateMipmap(Context *context, GLenum target)
4600{
4601 if (!ValidTextureTarget(context, target))
4602 {
4603 context->handleError(Error(GL_INVALID_ENUM));
4604 return false;
4605 }
4606
4607 Texture *texture = context->getTargetTexture(target);
4608
4609 if (texture == nullptr)
4610 {
4611 context->handleError(Error(GL_INVALID_OPERATION));
4612 return false;
4613 }
4614
4615 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4616
4617 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4618 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4619 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4620 {
4621 context->handleError(Error(GL_INVALID_OPERATION));
4622 return false;
4623 }
4624
Jamie Madilla3944d42016-07-22 22:13:26 -04004625 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4626 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4627 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004628
4629 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4630 // unsized formats or that are color renderable and filterable. Since we do not track if
4631 // the texture was created with sized or unsized format (only sized formats are stored),
4632 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4633 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4634 // textures since they're the only texture format that can be created with unsized formats
4635 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4636 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004637 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4638 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004639 {
4640 context->handleError(Error(GL_INVALID_OPERATION));
4641 return false;
4642 }
4643
4644 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004645 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004646 {
4647 context->handleError(Error(GL_INVALID_OPERATION));
4648 return false;
4649 }
4650
4651 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004652 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004653 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4654 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4655 {
Geoff Lang55482a12016-11-21 16:54:01 -05004656 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004657 context->handleError(Error(GL_INVALID_OPERATION));
4658 return false;
4659 }
4660
4661 // Cube completeness check
4662 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4663 {
4664 context->handleError(Error(GL_INVALID_OPERATION));
4665 return false;
4666 }
4667
4668 return true;
4669}
4670
Olli Etuaho41997e72016-03-10 13:38:39 +02004671bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4672{
4673 return ValidateGenOrDelete(context, n);
4674}
4675
4676bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4677{
4678 return ValidateGenOrDelete(context, n);
4679}
4680
4681bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4682{
4683 return ValidateGenOrDelete(context, n);
4684}
4685
4686bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4687{
4688 return ValidateGenOrDelete(context, n);
4689}
4690
4691bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4692{
4693 return ValidateGenOrDelete(context, n);
4694}
4695
4696bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4697{
4698 return ValidateGenOrDelete(context, n);
4699}
4700
4701bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4702{
4703 return ValidateGenOrDelete(context, n);
4704}
4705
4706bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4707{
4708 return ValidateGenOrDelete(context, n);
4709}
4710
4711bool ValidateGenOrDelete(Context *context, GLint n)
4712{
4713 if (n < 0)
4714 {
Jamie Madill437fa652016-05-03 15:13:24 -04004715 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004716 return false;
4717 }
4718 return true;
4719}
4720
Geoff Langf41a7152016-09-19 15:11:17 -04004721bool ValidateEnable(Context *context, GLenum cap)
4722{
4723 if (!ValidCap(context, cap, false))
4724 {
4725 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4726 return false;
4727 }
4728
4729 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4730 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4731 {
4732 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4733 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4734
4735 // We also output an error message to the debugger window if tracing is active, so that
4736 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05004737 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04004738 return false;
4739 }
4740
4741 return true;
4742}
4743
4744bool ValidateDisable(Context *context, GLenum cap)
4745{
4746 if (!ValidCap(context, cap, false))
4747 {
4748 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4749 return false;
4750 }
4751
4752 return true;
4753}
4754
4755bool ValidateIsEnabled(Context *context, GLenum cap)
4756{
4757 if (!ValidCap(context, cap, true))
4758 {
4759 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4760 return false;
4761 }
4762
4763 return true;
4764}
4765
Geoff Langff5b2d52016-09-07 11:32:23 -04004766bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4767{
4768 if (!context->getExtensions().robustClientMemory)
4769 {
4770 context->handleError(
4771 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4772 return false;
4773 }
4774
4775 if (bufSize < 0)
4776 {
4777 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4778 return false;
4779 }
4780
4781 return true;
4782}
4783
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004784bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4785{
4786 if (bufSize < numParams)
4787 {
4788 context->handleError(Error(GL_INVALID_OPERATION,
4789 "%u parameters are required but %i were provided.", numParams,
4790 bufSize));
4791 return false;
4792 }
4793
4794 return true;
4795}
4796
Geoff Langff5b2d52016-09-07 11:32:23 -04004797bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4798 GLenum target,
4799 GLenum attachment,
4800 GLenum pname,
4801 GLsizei *numParams)
4802{
4803 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4804 *numParams = 1;
4805
4806 if (!ValidFramebufferTarget(target))
4807 {
4808 context->handleError(Error(GL_INVALID_ENUM));
4809 return false;
4810 }
4811
4812 int clientVersion = context->getClientMajorVersion();
4813
4814 switch (pname)
4815 {
4816 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4817 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4818 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4819 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4820 break;
4821
4822 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4823 if (clientVersion < 3 && !context->getExtensions().sRGB)
4824 {
4825 context->handleError(Error(GL_INVALID_ENUM));
4826 return false;
4827 }
4828 break;
4829
4830 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4831 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4832 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4833 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4834 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4835 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4836 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4837 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4838 if (clientVersion < 3)
4839 {
4840 context->handleError(Error(GL_INVALID_ENUM));
4841 return false;
4842 }
4843 break;
4844
4845 default:
4846 context->handleError(Error(GL_INVALID_ENUM));
4847 return false;
4848 }
4849
4850 // Determine if the attachment is a valid enum
4851 switch (attachment)
4852 {
4853 case GL_BACK:
4854 case GL_FRONT:
4855 case GL_DEPTH:
4856 case GL_STENCIL:
4857 case GL_DEPTH_STENCIL_ATTACHMENT:
4858 if (clientVersion < 3)
4859 {
4860 context->handleError(Error(GL_INVALID_ENUM));
4861 return false;
4862 }
4863 break;
4864
4865 case GL_DEPTH_ATTACHMENT:
4866 case GL_STENCIL_ATTACHMENT:
4867 break;
4868
4869 default:
4870 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4871 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4872 {
4873 context->handleError(Error(GL_INVALID_ENUM));
4874 return false;
4875 }
4876 break;
4877 }
4878
4879 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4880 ASSERT(framebuffer);
4881
4882 if (framebuffer->id() == 0)
4883 {
4884 if (clientVersion < 3)
4885 {
4886 context->handleError(Error(GL_INVALID_OPERATION));
4887 return false;
4888 }
4889
4890 switch (attachment)
4891 {
4892 case GL_BACK:
4893 case GL_DEPTH:
4894 case GL_STENCIL:
4895 break;
4896
4897 default:
4898 context->handleError(Error(GL_INVALID_OPERATION));
4899 return false;
4900 }
4901 }
4902 else
4903 {
4904 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4905 {
4906 // Valid attachment query
4907 }
4908 else
4909 {
4910 switch (attachment)
4911 {
4912 case GL_DEPTH_ATTACHMENT:
4913 case GL_STENCIL_ATTACHMENT:
4914 break;
4915
4916 case GL_DEPTH_STENCIL_ATTACHMENT:
4917 if (!framebuffer->hasValidDepthStencil())
4918 {
4919 context->handleError(Error(GL_INVALID_OPERATION));
4920 return false;
4921 }
4922 break;
4923
4924 default:
4925 context->handleError(Error(GL_INVALID_OPERATION));
4926 return false;
4927 }
4928 }
4929 }
4930
4931 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4932 if (attachmentObject)
4933 {
4934 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4935 attachmentObject->type() == GL_TEXTURE ||
4936 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4937
4938 switch (pname)
4939 {
4940 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4941 if (attachmentObject->type() != GL_RENDERBUFFER &&
4942 attachmentObject->type() != GL_TEXTURE)
4943 {
4944 context->handleError(Error(GL_INVALID_ENUM));
4945 return false;
4946 }
4947 break;
4948
4949 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4950 if (attachmentObject->type() != GL_TEXTURE)
4951 {
4952 context->handleError(Error(GL_INVALID_ENUM));
4953 return false;
4954 }
4955 break;
4956
4957 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4958 if (attachmentObject->type() != GL_TEXTURE)
4959 {
4960 context->handleError(Error(GL_INVALID_ENUM));
4961 return false;
4962 }
4963 break;
4964
4965 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4966 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4967 {
4968 context->handleError(Error(GL_INVALID_OPERATION));
4969 return false;
4970 }
4971 break;
4972
4973 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4974 if (attachmentObject->type() != GL_TEXTURE)
4975 {
4976 context->handleError(Error(GL_INVALID_ENUM));
4977 return false;
4978 }
4979 break;
4980
4981 default:
4982 break;
4983 }
4984 }
4985 else
4986 {
4987 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4988 // is NONE, then querying any other pname will generate INVALID_ENUM.
4989
4990 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4991 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4992 // INVALID_OPERATION for all other pnames
4993
4994 switch (pname)
4995 {
4996 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4997 break;
4998
4999 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5000 if (clientVersion < 3)
5001 {
5002 context->handleError(Error(GL_INVALID_ENUM));
5003 return false;
5004 }
5005 break;
5006
5007 default:
5008 if (clientVersion < 3)
5009 {
5010 context->handleError(Error(GL_INVALID_ENUM));
5011 return false;
5012 }
5013 else
5014 {
5015 context->handleError(Error(GL_INVALID_OPERATION));
5016 return false;
5017 }
5018 }
5019 }
5020
5021 return true;
5022}
5023
5024bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5025 GLenum target,
5026 GLenum attachment,
5027 GLenum pname,
5028 GLsizei bufSize,
5029 GLsizei *numParams)
5030{
5031 if (!ValidateRobustEntryPoint(context, bufSize))
5032 {
5033 return false;
5034 }
5035
5036 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5037 {
5038 return false;
5039 }
5040
5041 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5042 {
5043 return false;
5044 }
5045
5046 return true;
5047}
5048
5049bool ValidateGetBufferParameteriv(ValidationContext *context,
5050 GLenum target,
5051 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005052 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005053{
Geoff Langebebe1c2016-10-14 12:01:31 -04005054 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005055}
5056
5057bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5058 GLenum target,
5059 GLenum pname,
5060 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005061 GLsizei *length,
5062 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005063{
5064 if (!ValidateRobustEntryPoint(context, bufSize))
5065 {
5066 return false;
5067 }
5068
Geoff Langebebe1c2016-10-14 12:01:31 -04005069 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005070 {
5071 return false;
5072 }
5073
Geoff Langebebe1c2016-10-14 12:01:31 -04005074 if (!ValidateRobustBufferSize(context, bufSize, *length))
5075 {
5076 return false;
5077 }
5078
5079 return true;
5080}
5081
5082bool ValidateGetBufferParameteri64v(ValidationContext *context,
5083 GLenum target,
5084 GLenum pname,
5085 GLint64 *params)
5086{
5087 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5088}
5089
5090bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5091 GLenum target,
5092 GLenum pname,
5093 GLsizei bufSize,
5094 GLsizei *length,
5095 GLint64 *params)
5096{
5097 if (!ValidateRobustEntryPoint(context, bufSize))
5098 {
5099 return false;
5100 }
5101
5102 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5103 {
5104 return false;
5105 }
5106
5107 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005108 {
5109 return false;
5110 }
5111
5112 return true;
5113}
5114
5115bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5116{
5117 // Currently, all GetProgramiv queries return 1 parameter
5118 *numParams = 1;
5119
5120 Program *programObject = GetValidProgram(context, program);
5121 if (!programObject)
5122 {
5123 return false;
5124 }
5125
5126 switch (pname)
5127 {
5128 case GL_DELETE_STATUS:
5129 case GL_LINK_STATUS:
5130 case GL_VALIDATE_STATUS:
5131 case GL_INFO_LOG_LENGTH:
5132 case GL_ATTACHED_SHADERS:
5133 case GL_ACTIVE_ATTRIBUTES:
5134 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5135 case GL_ACTIVE_UNIFORMS:
5136 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5137 break;
5138
5139 case GL_PROGRAM_BINARY_LENGTH:
5140 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5141 {
5142 context->handleError(Error(GL_INVALID_ENUM,
5143 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5144 "GL_OES_get_program_binary or ES 3.0."));
5145 return false;
5146 }
5147 break;
5148
5149 case GL_ACTIVE_UNIFORM_BLOCKS:
5150 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5151 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5152 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5153 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5154 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5155 if (context->getClientMajorVersion() < 3)
5156 {
5157 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5158 return false;
5159 }
5160 break;
5161
5162 default:
5163 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5164 return false;
5165 }
5166
5167 return true;
5168}
5169
5170bool ValidateGetProgramivRobustANGLE(Context *context,
5171 GLuint program,
5172 GLenum pname,
5173 GLsizei bufSize,
5174 GLsizei *numParams)
5175{
5176 if (!ValidateRobustEntryPoint(context, bufSize))
5177 {
5178 return false;
5179 }
5180
5181 if (!ValidateGetProgramiv(context, program, pname, numParams))
5182 {
5183 return false;
5184 }
5185
5186 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5187 {
5188 return false;
5189 }
5190
5191 return true;
5192}
5193
Geoff Lang740d9022016-10-07 11:20:52 -04005194bool ValidateGetRenderbufferParameteriv(Context *context,
5195 GLenum target,
5196 GLenum pname,
5197 GLint *params)
5198{
5199 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5200}
5201
5202bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5203 GLenum target,
5204 GLenum pname,
5205 GLsizei bufSize,
5206 GLsizei *length,
5207 GLint *params)
5208{
5209 if (!ValidateRobustEntryPoint(context, bufSize))
5210 {
5211 return false;
5212 }
5213
5214 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5215 {
5216 return false;
5217 }
5218
5219 if (!ValidateRobustBufferSize(context, bufSize, *length))
5220 {
5221 return false;
5222 }
5223
5224 return true;
5225}
5226
Geoff Langd7d0ed32016-10-07 11:33:51 -04005227bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5228{
5229 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5230}
5231
5232bool ValidateGetShaderivRobustANGLE(Context *context,
5233 GLuint shader,
5234 GLenum pname,
5235 GLsizei bufSize,
5236 GLsizei *length,
5237 GLint *params)
5238{
5239 if (!ValidateRobustEntryPoint(context, bufSize))
5240 {
5241 return false;
5242 }
5243
5244 if (!ValidateGetShaderivBase(context, shader, pname, length))
5245 {
5246 return false;
5247 }
5248
5249 if (!ValidateRobustBufferSize(context, bufSize, *length))
5250 {
5251 return false;
5252 }
5253
5254 return true;
5255}
5256
Geoff Langc1984ed2016-10-07 12:41:00 -04005257bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5258{
5259 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5260}
5261
5262bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5263 GLenum target,
5264 GLenum pname,
5265 GLsizei bufSize,
5266 GLsizei *length,
5267 GLfloat *params)
5268{
5269 if (!ValidateRobustEntryPoint(context, bufSize))
5270 {
5271 return false;
5272 }
5273
5274 if (!ValidateGetTexParameterBase(context, target, pname, length))
5275 {
5276 return false;
5277 }
5278
5279 if (!ValidateRobustBufferSize(context, bufSize, *length))
5280 {
5281 return false;
5282 }
5283
5284 return true;
5285}
5286
5287bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5288{
5289 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5290}
5291
5292bool ValidateGetTexParameterivRobustANGLE(Context *context,
5293 GLenum target,
5294 GLenum pname,
5295 GLsizei bufSize,
5296 GLsizei *length,
5297 GLint *params)
5298{
5299 if (!ValidateRobustEntryPoint(context, bufSize))
5300 {
5301 return false;
5302 }
5303
5304 if (!ValidateGetTexParameterBase(context, target, pname, length))
5305 {
5306 return false;
5307 }
5308
5309 if (!ValidateRobustBufferSize(context, bufSize, *length))
5310 {
5311 return false;
5312 }
5313
5314 return true;
5315}
5316
5317bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5318{
5319 return ValidateTexParameterBase(context, target, pname, -1, &param);
5320}
5321
5322bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5323{
5324 return ValidateTexParameterBase(context, target, pname, -1, params);
5325}
5326
5327bool ValidateTexParameterfvRobustANGLE(Context *context,
5328 GLenum target,
5329 GLenum pname,
5330 GLsizei bufSize,
5331 const GLfloat *params)
5332{
5333 if (!ValidateRobustEntryPoint(context, bufSize))
5334 {
5335 return false;
5336 }
5337
5338 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5339}
5340
5341bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5342{
5343 return ValidateTexParameterBase(context, target, pname, -1, &param);
5344}
5345
5346bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5347{
5348 return ValidateTexParameterBase(context, target, pname, -1, params);
5349}
5350
5351bool ValidateTexParameterivRobustANGLE(Context *context,
5352 GLenum target,
5353 GLenum pname,
5354 GLsizei bufSize,
5355 const GLint *params)
5356{
5357 if (!ValidateRobustEntryPoint(context, bufSize))
5358 {
5359 return false;
5360 }
5361
5362 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5363}
5364
5365bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5366{
5367 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5368}
5369
5370bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5371 GLuint sampler,
5372 GLenum pname,
5373 GLuint bufSize,
5374 GLsizei *length,
5375 GLfloat *params)
5376{
5377 if (!ValidateRobustEntryPoint(context, bufSize))
5378 {
5379 return false;
5380 }
5381
5382 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5383 {
5384 return false;
5385 }
5386
5387 if (!ValidateRobustBufferSize(context, bufSize, *length))
5388 {
5389 return false;
5390 }
5391
5392 return true;
5393}
5394
5395bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5396{
5397 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5398}
5399
5400bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5401 GLuint sampler,
5402 GLenum pname,
5403 GLuint bufSize,
5404 GLsizei *length,
5405 GLint *params)
5406{
5407 if (!ValidateRobustEntryPoint(context, bufSize))
5408 {
5409 return false;
5410 }
5411
5412 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5413 {
5414 return false;
5415 }
5416
5417 if (!ValidateRobustBufferSize(context, bufSize, *length))
5418 {
5419 return false;
5420 }
5421
5422 return true;
5423}
5424
5425bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5426{
5427 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5428}
5429
5430bool ValidateSamplerParameterfv(Context *context,
5431 GLuint sampler,
5432 GLenum pname,
5433 const GLfloat *params)
5434{
5435 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5436}
5437
5438bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5439 GLuint sampler,
5440 GLenum pname,
5441 GLsizei bufSize,
5442 const GLfloat *params)
5443{
5444 if (!ValidateRobustEntryPoint(context, bufSize))
5445 {
5446 return false;
5447 }
5448
5449 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5450}
5451
5452bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5453{
5454 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5455}
5456
5457bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5458{
5459 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5460}
5461
5462bool ValidateSamplerParameterivRobustANGLE(Context *context,
5463 GLuint sampler,
5464 GLenum pname,
5465 GLsizei bufSize,
5466 const GLint *params)
5467{
5468 if (!ValidateRobustEntryPoint(context, bufSize))
5469 {
5470 return false;
5471 }
5472
5473 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5474}
5475
Geoff Lang0b031062016-10-13 14:30:04 -04005476bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5477{
5478 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5479}
5480
5481bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5482 GLuint index,
5483 GLenum pname,
5484 GLsizei bufSize,
5485 GLsizei *length,
5486 GLfloat *params)
5487{
5488 if (!ValidateRobustEntryPoint(context, bufSize))
5489 {
5490 return false;
5491 }
5492
5493 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5494 {
5495 return false;
5496 }
5497
5498 if (!ValidateRobustBufferSize(context, bufSize, *length))
5499 {
5500 return false;
5501 }
5502
5503 return true;
5504}
5505
5506bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5507{
5508 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5509}
5510
5511bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5512 GLuint index,
5513 GLenum pname,
5514 GLsizei bufSize,
5515 GLsizei *length,
5516 GLint *params)
5517{
5518 if (!ValidateRobustEntryPoint(context, bufSize))
5519 {
5520 return false;
5521 }
5522
5523 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5524 {
5525 return false;
5526 }
5527
5528 if (!ValidateRobustBufferSize(context, bufSize, *length))
5529 {
5530 return false;
5531 }
5532
5533 return true;
5534}
5535
5536bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5537{
5538 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5539}
5540
5541bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5542 GLuint index,
5543 GLenum pname,
5544 GLsizei bufSize,
5545 GLsizei *length,
5546 void **pointer)
5547{
5548 if (!ValidateRobustEntryPoint(context, bufSize))
5549 {
5550 return false;
5551 }
5552
5553 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5554 {
5555 return false;
5556 }
5557
5558 if (!ValidateRobustBufferSize(context, bufSize, *length))
5559 {
5560 return false;
5561 }
5562
5563 return true;
5564}
5565
5566bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5567{
5568 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5569}
5570
5571bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5572 GLuint index,
5573 GLenum pname,
5574 GLsizei bufSize,
5575 GLsizei *length,
5576 GLint *params)
5577{
5578 if (!ValidateRobustEntryPoint(context, bufSize))
5579 {
5580 return false;
5581 }
5582
5583 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5584 {
5585 return false;
5586 }
5587
5588 if (!ValidateRobustBufferSize(context, bufSize, *length))
5589 {
5590 return false;
5591 }
5592
5593 return true;
5594}
5595
5596bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5597{
5598 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5599}
5600
5601bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5602 GLuint index,
5603 GLenum pname,
5604 GLsizei bufSize,
5605 GLsizei *length,
5606 GLuint *params)
5607{
5608 if (!ValidateRobustEntryPoint(context, bufSize))
5609 {
5610 return false;
5611 }
5612
5613 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5614 {
5615 return false;
5616 }
5617
5618 if (!ValidateRobustBufferSize(context, bufSize, *length))
5619 {
5620 return false;
5621 }
5622
5623 return true;
5624}
5625
Geoff Lang6899b872016-10-14 11:30:13 -04005626bool ValidateGetActiveUniformBlockiv(Context *context,
5627 GLuint program,
5628 GLuint uniformBlockIndex,
5629 GLenum pname,
5630 GLint *params)
5631{
5632 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5633}
5634
5635bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5636 GLuint program,
5637 GLuint uniformBlockIndex,
5638 GLenum pname,
5639 GLsizei bufSize,
5640 GLsizei *length,
5641 GLint *params)
5642{
5643 if (!ValidateRobustEntryPoint(context, bufSize))
5644 {
5645 return false;
5646 }
5647
5648 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5649 {
5650 return false;
5651 }
5652
5653 if (!ValidateRobustBufferSize(context, bufSize, *length))
5654 {
5655 return false;
5656 }
5657
5658 return true;
5659}
5660
Geoff Lang0a9661f2016-10-20 10:59:20 -07005661bool ValidateGetInternalFormativ(Context *context,
5662 GLenum target,
5663 GLenum internalformat,
5664 GLenum pname,
5665 GLsizei bufSize,
5666 GLint *params)
5667{
5668 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5669 nullptr);
5670}
5671
5672bool ValidateGetInternalFormativRobustANGLE(Context *context,
5673 GLenum target,
5674 GLenum internalformat,
5675 GLenum pname,
5676 GLsizei bufSize,
5677 GLsizei *length,
5678 GLint *params)
5679{
5680 if (!ValidateRobustEntryPoint(context, bufSize))
5681 {
5682 return false;
5683 }
5684
5685 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5686 {
5687 return false;
5688 }
5689
5690 if (!ValidateRobustBufferSize(context, bufSize, *length))
5691 {
5692 return false;
5693 }
5694
5695 return true;
5696}
5697
Jamie Madillc29968b2016-01-20 11:17:23 -05005698} // namespace gl