blob: afd7a5a515af0ef62e03df683acc76f7fe420cba [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();
49 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040050 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
51 {
52 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill63805b42015-08-25 13:17:39 -040053 if (program->isAttribLocationActive(attributeIndex) && attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040054 {
55 gl::Buffer *buffer = attrib.buffer.get();
56
57 if (buffer)
58 {
Corentin Wallez71168a02016-12-19 15:11:18 -080059 GLint maxVertexElement = 0;
60 bool readsData = false;
Corentin Wallez92db6942016-12-09 13:10:36 -050061 if (attrib.divisor == 0)
Jamie Madill1ca74672015-07-21 15:14:11 -040062 {
Corentin Wallez92db6942016-12-09 13:10:36 -050063 readsData = vertexCount > 0;
Corentin Wallez71168a02016-12-19 15:11:18 -080064 maxVertexElement = maxVertex;
Jamie Madill1ca74672015-07-21 15:14:11 -040065 }
Corentin Wallez92db6942016-12-09 13:10:36 -050066 else if (primcount > 0)
67 {
68 readsData = true;
Corentin Wallez71168a02016-12-19 15:11:18 -080069 maxVertexElement = (primcount - 1) / attrib.divisor;
Corentin Wallez92db6942016-12-09 13:10:36 -050070 }
Jamie Madill1ca74672015-07-21 15:14:11 -040071
72 // If we're drawing zero vertices, we have enough data.
Corentin Wallez92db6942016-12-09 13:10:36 -050073 if (readsData)
Jamie Madill1ca74672015-07-21 15:14:11 -040074 {
Corentin Wallez71168a02016-12-19 15:11:18 -080075 // We do manual overflow checks here instead of using safe_math.h because it was
76 // a bottleneck. Thanks to some properties of GL we know inequalities that can
77 // help us make the overflow checks faster.
Corentin Wallez92db6942016-12-09 13:10:36 -050078
Corentin Wallez71168a02016-12-19 15:11:18 -080079 // The max possible attribSize is 16 for a vector of 4 32 bit values.
80 constexpr uint64_t kMaxAttribSize = 16;
81 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
82 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
83
84 // We know attribStride is given as a GLsizei which is typedefed to int.
85 // We also know an upper bound for attribSize.
86 static_assert(std::is_same<int, GLsizei>::value, "");
87 uint64_t attribStride = ComputeVertexAttributeStride(attrib);
88 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
89 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
90
91 // Computing the max offset using uint64_t without attrib.offset is overflow
92 // safe. Note: Last vertex element does not take the full stride!
93 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
94 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
95
96 // An overflow can happen when adding the offset, check for it.
97 uint64_t attribOffset = attrib.offset;
98 if (attribDataSizeNoOffset > kUint64Max - attrib.offset)
Corentin Wallez92db6942016-12-09 13:10:36 -050099 {
100 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
101 return false;
102 }
Corentin Wallez71168a02016-12-19 15:11:18 -0800103 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
Jamie Madill1ca74672015-07-21 15:14:11 -0400104
105 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
106 // We can return INVALID_OPERATION if our vertex attribute does not have
107 // enough backing data.
Corentin Wallez71168a02016-12-19 15:11:18 -0800108 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
Jamie Madill1ca74672015-07-21 15:14:11 -0400109 {
Jamie Madill437fa652016-05-03 15:13:24 -0400110 context->handleError(
Jamie Madillbc4c4bc2016-03-23 21:04:43 -0400111 Error(GL_INVALID_OPERATION,
112 "Vertex buffer is not big enough for the draw call"));
Jamie Madill1ca74672015-07-21 15:14:11 -0400113 return false;
114 }
115 }
116 }
Corentin Wallez327411e2016-12-09 11:09:17 -0500117 else if (webglCompatibility)
118 {
119 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
120 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
121 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then
122 // calls to drawArrays or drawElements will generate an INVALID_OPERATION error.
123 context->handleError(
124 Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer."));
125 }
Jamie Madill1ca74672015-07-21 15:14:11 -0400126 else if (attrib.pointer == NULL)
127 {
128 // This is an application error that would normally result in a crash,
129 // but we catch it and return an error
Jamie Madill437fa652016-05-03 15:13:24 -0400130 context->handleError(Error(
Jamie Madill1ca74672015-07-21 15:14:11 -0400131 GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
132 return false;
133 }
134 }
135 }
136
137 return true;
138}
139
Geoff Langf607c602016-09-21 11:46:48 -0400140bool ValidReadPixelsFormatType(ValidationContext *context,
141 GLenum framebufferComponentType,
142 GLenum format,
143 GLenum type)
144{
145 switch (framebufferComponentType)
146 {
147 case GL_UNSIGNED_NORMALIZED:
148 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
149 // ReadPixels with BGRA even if the extension is not present
150 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
151 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
152 type == GL_UNSIGNED_BYTE);
153
154 case GL_SIGNED_NORMALIZED:
155 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
156
157 case GL_INT:
158 return (format == GL_RGBA_INTEGER && type == GL_INT);
159
160 case GL_UNSIGNED_INT:
161 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
162
163 case GL_FLOAT:
164 return (format == GL_RGBA && type == GL_FLOAT);
165
166 default:
167 UNREACHABLE();
168 return false;
169 }
170}
171
Geoff Langf41a7152016-09-19 15:11:17 -0400172bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500173{
174 switch (cap)
175 {
Geoff Langf41a7152016-09-19 15:11:17 -0400176 // EXT_multisample_compatibility
177 case GL_MULTISAMPLE_EXT:
178 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
179 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300180
Geoff Langf41a7152016-09-19 15:11:17 -0400181 case GL_CULL_FACE:
182 case GL_POLYGON_OFFSET_FILL:
183 case GL_SAMPLE_ALPHA_TO_COVERAGE:
184 case GL_SAMPLE_COVERAGE:
185 case GL_SCISSOR_TEST:
186 case GL_STENCIL_TEST:
187 case GL_DEPTH_TEST:
188 case GL_BLEND:
189 case GL_DITHER:
190 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500191
Geoff Langf41a7152016-09-19 15:11:17 -0400192 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
193 case GL_RASTERIZER_DISCARD:
194 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500195
Geoff Langf41a7152016-09-19 15:11:17 -0400196 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
197 case GL_DEBUG_OUTPUT:
198 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500199
Geoff Langf41a7152016-09-19 15:11:17 -0400200 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
201 return queryOnly && context->getExtensions().bindGeneratesResource;
202
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700203 case GL_FRAMEBUFFER_SRGB_EXT:
204 return context->getExtensions().sRGBWriteControl;
205
Geoff Lang3b573612016-10-31 14:08:10 -0400206 case GL_SAMPLE_MASK:
Geoff Lang3b573612016-10-31 14:08:10 -0400207 return context->getClientVersion() >= Version(3, 1);
208
Geoff Langf41a7152016-09-19 15:11:17 -0400209 default:
210 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500211 }
212}
213
Geoff Lang62fce5b2016-09-30 10:46:35 -0400214bool ValidateReadPixelsBase(ValidationContext *context,
215 GLint x,
216 GLint y,
217 GLsizei width,
218 GLsizei height,
219 GLenum format,
220 GLenum type,
221 GLsizei bufSize,
222 GLsizei *length,
223 GLvoid *pixels)
224{
225 if (length != nullptr)
226 {
227 *length = 0;
228 }
229
230 if (width < 0 || height < 0)
231 {
232 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
233 return false;
234 }
235
236 auto readFramebuffer = context->getGLState().getReadFramebuffer();
237
238 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
239 {
240 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
241 return false;
242 }
243
244 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
245 {
246 context->handleError(Error(GL_INVALID_OPERATION));
247 return false;
248 }
249
250 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
251 ASSERT(framebuffer);
252
253 if (framebuffer->getReadBufferState() == GL_NONE)
254 {
255 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
256 return false;
257 }
258
259 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500260 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
261 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
262 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
263 // situation is an application error that would lead to a crash in ANGLE.
264 if (readBuffer == nullptr)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400265 {
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500266 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
Geoff Lang62fce5b2016-09-30 10:46:35 -0400267 return false;
268 }
269
270 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
271 GLenum currentType = framebuffer->getImplementationColorReadType();
272 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
273
274 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
275 bool validFormatTypeCombination =
276 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
277
278 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
279 {
280 context->handleError(Error(GL_INVALID_OPERATION));
281 return false;
282 }
283
284 // Check for pixel pack buffer related API errors
285 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
286 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
287 {
288 // ...the buffer object's data store is currently mapped.
289 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
290 return false;
291 }
292
293 // .. the data would be packed to the buffer object such that the memory writes required
294 // would exceed the data store size.
295 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
296 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
297 const gl::Extents size(width, height, 1);
298 const auto &pack = context->getGLState().getPackState();
299
300 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
301 if (endByteOrErr.isError())
302 {
303 context->handleError(endByteOrErr.getError());
304 return false;
305 }
306
307 size_t endByte = endByteOrErr.getResult();
308 if (bufSize >= 0)
309 {
310
311 if (static_cast<size_t>(bufSize) < endByte)
312 {
313 context->handleError(
314 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
315 return false;
316 }
317 }
318
319 if (pixelPackBuffer != nullptr)
320 {
321 CheckedNumeric<size_t> checkedEndByte(endByte);
322 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
323 checkedEndByte += checkedOffset;
324
325 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
326 {
327 // Overflow past the end of the buffer
328 context->handleError(
329 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
330 return false;
331 }
332 }
333
334 if (length != nullptr)
335 {
336 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
337 {
338 context->handleError(
339 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
340 return false;
341 }
342
343 *length = static_cast<GLsizei>(endByte);
344 }
345
346 return true;
347}
348
Geoff Lang740d9022016-10-07 11:20:52 -0400349bool ValidateGetRenderbufferParameterivBase(Context *context,
350 GLenum target,
351 GLenum pname,
352 GLsizei *length)
353{
354 if (length)
355 {
356 *length = 0;
357 }
358
359 if (target != GL_RENDERBUFFER)
360 {
361 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
362 return false;
363 }
364
365 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
366 if (renderbuffer == nullptr)
367 {
368 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
369 return false;
370 }
371
372 switch (pname)
373 {
374 case GL_RENDERBUFFER_WIDTH:
375 case GL_RENDERBUFFER_HEIGHT:
376 case GL_RENDERBUFFER_INTERNAL_FORMAT:
377 case GL_RENDERBUFFER_RED_SIZE:
378 case GL_RENDERBUFFER_GREEN_SIZE:
379 case GL_RENDERBUFFER_BLUE_SIZE:
380 case GL_RENDERBUFFER_ALPHA_SIZE:
381 case GL_RENDERBUFFER_DEPTH_SIZE:
382 case GL_RENDERBUFFER_STENCIL_SIZE:
383 break;
384
385 case GL_RENDERBUFFER_SAMPLES_ANGLE:
386 if (!context->getExtensions().framebufferMultisample)
387 {
388 context->handleError(
389 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
390 return false;
391 }
392 break;
393
394 default:
395 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
396 return false;
397 }
398
399 if (length)
400 {
401 *length = 1;
402 }
403 return true;
404}
405
Geoff Langd7d0ed32016-10-07 11:33:51 -0400406bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
407{
408 if (length)
409 {
410 *length = 0;
411 }
412
413 if (GetValidShader(context, shader) == nullptr)
414 {
415 return false;
416 }
417
418 switch (pname)
419 {
420 case GL_SHADER_TYPE:
421 case GL_DELETE_STATUS:
422 case GL_COMPILE_STATUS:
423 case GL_INFO_LOG_LENGTH:
424 case GL_SHADER_SOURCE_LENGTH:
425 break;
426
427 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
428 if (!context->getExtensions().translatedShaderSource)
429 {
430 context->handleError(
431 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
432 return false;
433 }
434 break;
435
436 default:
437 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
438 return false;
439 }
440
441 if (length)
442 {
443 *length = 1;
444 }
445 return true;
446}
447
Geoff Langc1984ed2016-10-07 12:41:00 -0400448bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
449{
450 if (length)
451 {
452 *length = 0;
453 }
454
455 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
456 {
457 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
458 return false;
459 }
460
461 if (context->getTargetTexture(target) == nullptr)
462 {
463 // Should only be possible for external textures
464 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
465 return false;
466 }
467
468 switch (pname)
469 {
470 case GL_TEXTURE_MAG_FILTER:
471 case GL_TEXTURE_MIN_FILTER:
472 case GL_TEXTURE_WRAP_S:
473 case GL_TEXTURE_WRAP_T:
474 break;
475
476 case GL_TEXTURE_USAGE_ANGLE:
477 if (!context->getExtensions().textureUsage)
478 {
479 context->handleError(
480 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
481 return false;
482 }
483 break;
484
485 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
486 if (!context->getExtensions().textureFilterAnisotropic)
487 {
488 context->handleError(
489 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
490 return false;
491 }
492 break;
493
494 case GL_TEXTURE_IMMUTABLE_FORMAT:
495 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
496 {
497 context->handleError(
498 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
499 return false;
500 }
501 break;
502
503 case GL_TEXTURE_WRAP_R:
504 case GL_TEXTURE_IMMUTABLE_LEVELS:
505 case GL_TEXTURE_SWIZZLE_R:
506 case GL_TEXTURE_SWIZZLE_G:
507 case GL_TEXTURE_SWIZZLE_B:
508 case GL_TEXTURE_SWIZZLE_A:
509 case GL_TEXTURE_BASE_LEVEL:
510 case GL_TEXTURE_MAX_LEVEL:
511 case GL_TEXTURE_MIN_LOD:
512 case GL_TEXTURE_MAX_LOD:
513 case GL_TEXTURE_COMPARE_MODE:
514 case GL_TEXTURE_COMPARE_FUNC:
515 if (context->getClientMajorVersion() < 3)
516 {
517 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
518 return false;
519 }
520 break;
521
Geoff Lang81c6b572016-10-19 14:07:52 -0700522 case GL_TEXTURE_SRGB_DECODE_EXT:
523 if (!context->getExtensions().textureSRGBDecode)
524 {
525 context->handleError(
526 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
527 return false;
528 }
529 break;
530
Geoff Langc1984ed2016-10-07 12:41:00 -0400531 default:
532 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
533 return false;
534 }
535
536 if (length)
537 {
538 *length = 1;
539 }
540 return true;
541}
542
543template <typename ParamType>
544bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
545{
546 switch (ConvertToGLenum(params[0]))
547 {
548 case GL_CLAMP_TO_EDGE:
549 break;
550
551 case GL_REPEAT:
552 case GL_MIRRORED_REPEAT:
553 if (isExternalTextureTarget)
554 {
555 // OES_EGL_image_external specifies this error.
556 context->handleError(Error(
557 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
558 return false;
559 }
560 break;
561
562 default:
563 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
564 return false;
565 }
566
567 return true;
568}
569
570template <typename ParamType>
571bool ValidateTextureMinFilterValue(Context *context,
572 ParamType *params,
573 bool isExternalTextureTarget)
574{
575 switch (ConvertToGLenum(params[0]))
576 {
577 case GL_NEAREST:
578 case GL_LINEAR:
579 break;
580
581 case GL_NEAREST_MIPMAP_NEAREST:
582 case GL_LINEAR_MIPMAP_NEAREST:
583 case GL_NEAREST_MIPMAP_LINEAR:
584 case GL_LINEAR_MIPMAP_LINEAR:
585 if (isExternalTextureTarget)
586 {
587 // OES_EGL_image_external specifies this error.
588 context->handleError(
589 Error(GL_INVALID_ENUM,
590 "external textures only support NEAREST and LINEAR filtering"));
591 return false;
592 }
593 break;
594
595 default:
596 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
597 return false;
598 }
599
600 return true;
601}
602
603template <typename ParamType>
604bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
605{
606 switch (ConvertToGLenum(params[0]))
607 {
608 case GL_NEAREST:
609 case GL_LINEAR:
610 break;
611
612 default:
613 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
614 return false;
615 }
616
617 return true;
618}
619
620template <typename ParamType>
621bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
622{
623 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
624 switch (ConvertToGLenum(params[0]))
625 {
626 case GL_NONE:
627 case GL_COMPARE_REF_TO_TEXTURE:
628 break;
629
630 default:
631 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
632 return false;
633 }
634
635 return true;
636}
637
638template <typename ParamType>
639bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
640{
641 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
642 switch (ConvertToGLenum(params[0]))
643 {
644 case GL_LEQUAL:
645 case GL_GEQUAL:
646 case GL_LESS:
647 case GL_GREATER:
648 case GL_EQUAL:
649 case GL_NOTEQUAL:
650 case GL_ALWAYS:
651 case GL_NEVER:
652 break;
653
654 default:
655 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
656 return false;
657 }
658
659 return true;
660}
661
662template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700663bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
664{
665 if (!context->getExtensions().textureSRGBDecode)
666 {
667 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
668 return false;
669 }
670
671 switch (ConvertToGLenum(params[0]))
672 {
673 case GL_DECODE_EXT:
674 case GL_SKIP_DECODE_EXT:
675 break;
676
677 default:
678 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
679 return false;
680 }
681
682 return true;
683}
684
685template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400686bool ValidateTexParameterBase(Context *context,
687 GLenum target,
688 GLenum pname,
689 GLsizei bufSize,
690 ParamType *params)
691{
692 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
693 {
694 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
695 return false;
696 }
697
698 if (context->getTargetTexture(target) == nullptr)
699 {
700 // Should only be possible for external textures
701 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
702 return false;
703 }
704
705 const GLsizei minBufSize = 1;
706 if (bufSize >= 0 && bufSize < minBufSize)
707 {
708 context->handleError(
709 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
710 return false;
711 }
712
713 switch (pname)
714 {
715 case GL_TEXTURE_WRAP_R:
716 case GL_TEXTURE_SWIZZLE_R:
717 case GL_TEXTURE_SWIZZLE_G:
718 case GL_TEXTURE_SWIZZLE_B:
719 case GL_TEXTURE_SWIZZLE_A:
720 case GL_TEXTURE_BASE_LEVEL:
721 case GL_TEXTURE_MAX_LEVEL:
722 case GL_TEXTURE_COMPARE_MODE:
723 case GL_TEXTURE_COMPARE_FUNC:
724 case GL_TEXTURE_MIN_LOD:
725 case GL_TEXTURE_MAX_LOD:
726 if (context->getClientMajorVersion() < 3)
727 {
728 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
729 return false;
730 }
731 if (target == GL_TEXTURE_EXTERNAL_OES &&
732 !context->getExtensions().eglImageExternalEssl3)
733 {
734 context->handleError(Error(GL_INVALID_ENUM,
735 "ES3 texture parameters are not available without "
736 "GL_OES_EGL_image_external_essl3."));
737 return false;
738 }
739 break;
740
741 default:
742 break;
743 }
744
745 switch (pname)
746 {
747 case GL_TEXTURE_WRAP_S:
748 case GL_TEXTURE_WRAP_T:
749 case GL_TEXTURE_WRAP_R:
750 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
751 {
752 return false;
753 }
754 break;
755
756 case GL_TEXTURE_MIN_FILTER:
757 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
758 {
759 return false;
760 }
761 break;
762
763 case GL_TEXTURE_MAG_FILTER:
764 if (!ValidateTextureMagFilterValue(context, params))
765 {
766 return false;
767 }
768 break;
769
770 case GL_TEXTURE_USAGE_ANGLE:
771 switch (ConvertToGLenum(params[0]))
772 {
773 case GL_NONE:
774 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
775 break;
776
777 default:
778 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
779 return false;
780 }
781 break;
782
783 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
784 if (!context->getExtensions().textureFilterAnisotropic)
785 {
786 context->handleError(
787 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
788 return false;
789 }
790
791 // we assume the parameter passed to this validation method is truncated, not rounded
792 if (params[0] < 1)
793 {
794 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
795 return false;
796 }
797 break;
798
799 case GL_TEXTURE_MIN_LOD:
800 case GL_TEXTURE_MAX_LOD:
801 // any value is permissible
802 break;
803
804 case GL_TEXTURE_COMPARE_MODE:
805 if (!ValidateTextureCompareModeValue(context, params))
806 {
807 return false;
808 }
809 break;
810
811 case GL_TEXTURE_COMPARE_FUNC:
812 if (!ValidateTextureCompareFuncValue(context, params))
813 {
814 return false;
815 }
816 break;
817
818 case GL_TEXTURE_SWIZZLE_R:
819 case GL_TEXTURE_SWIZZLE_G:
820 case GL_TEXTURE_SWIZZLE_B:
821 case GL_TEXTURE_SWIZZLE_A:
822 switch (ConvertToGLenum(params[0]))
823 {
824 case GL_RED:
825 case GL_GREEN:
826 case GL_BLUE:
827 case GL_ALPHA:
828 case GL_ZERO:
829 case GL_ONE:
830 break;
831
832 default:
833 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
834 return false;
835 }
836 break;
837
838 case GL_TEXTURE_BASE_LEVEL:
839 if (params[0] < 0)
840 {
841 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
842 return false;
843 }
844 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
845 {
846 context->handleError(
847 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
848 return false;
849 }
850 break;
851
852 case GL_TEXTURE_MAX_LEVEL:
853 if (params[0] < 0)
854 {
855 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
856 return false;
857 }
858 break;
859
Geoff Lang3b573612016-10-31 14:08:10 -0400860 case GL_DEPTH_STENCIL_TEXTURE_MODE:
861 if (context->getClientVersion() < Version(3, 1))
862 {
863 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
864 return false;
865 }
Geoff Lang9f090372016-12-02 10:20:43 -0500866 switch (ConvertToGLenum(params[0]))
867 {
868 case GL_DEPTH_COMPONENT:
869 case GL_STENCIL_INDEX:
870 break;
871
872 default:
873 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
874 return false;
875 }
Geoff Lang3b573612016-10-31 14:08:10 -0400876 break;
877
Geoff Lang81c6b572016-10-19 14:07:52 -0700878 case GL_TEXTURE_SRGB_DECODE_EXT:
879 if (!ValidateTextureSRGBDecodeValue(context, params))
880 {
881 return false;
882 }
883 break;
884
Geoff Langc1984ed2016-10-07 12:41:00 -0400885 default:
886 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
887 return false;
888 }
889
890 return true;
891}
892
893template <typename ParamType>
894bool ValidateSamplerParameterBase(Context *context,
895 GLuint sampler,
896 GLenum pname,
897 GLsizei bufSize,
898 ParamType *params)
899{
900 if (context->getClientMajorVersion() < 3)
901 {
902 context->handleError(
903 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
904 return false;
905 }
906
907 if (!context->isSampler(sampler))
908 {
909 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
910 return false;
911 }
912
913 const GLsizei minBufSize = 1;
914 if (bufSize >= 0 && bufSize < minBufSize)
915 {
916 context->handleError(
917 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
918 return false;
919 }
920
921 switch (pname)
922 {
923 case GL_TEXTURE_WRAP_S:
924 case GL_TEXTURE_WRAP_T:
925 case GL_TEXTURE_WRAP_R:
926 if (!ValidateTextureWrapModeValue(context, params, false))
927 {
928 return false;
929 }
930 break;
931
932 case GL_TEXTURE_MIN_FILTER:
933 if (!ValidateTextureMinFilterValue(context, params, false))
934 {
935 return false;
936 }
937 break;
938
939 case GL_TEXTURE_MAG_FILTER:
940 if (!ValidateTextureMagFilterValue(context, params))
941 {
942 return false;
943 }
944 break;
945
946 case GL_TEXTURE_MIN_LOD:
947 case GL_TEXTURE_MAX_LOD:
948 // any value is permissible
949 break;
950
951 case GL_TEXTURE_COMPARE_MODE:
952 if (!ValidateTextureCompareModeValue(context, params))
953 {
954 return false;
955 }
956 break;
957
958 case GL_TEXTURE_COMPARE_FUNC:
959 if (!ValidateTextureCompareFuncValue(context, params))
960 {
961 return false;
962 }
963 break;
964
Geoff Lang81c6b572016-10-19 14:07:52 -0700965 case GL_TEXTURE_SRGB_DECODE_EXT:
966 if (!ValidateTextureSRGBDecodeValue(context, params))
967 {
968 return false;
969 }
970 break;
971
Geoff Langc1984ed2016-10-07 12:41:00 -0400972 default:
973 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
974 return false;
975 }
976
977 return true;
978}
979
980bool ValidateGetSamplerParameterBase(Context *context,
981 GLuint sampler,
982 GLenum pname,
983 GLsizei *length)
984{
985 if (length)
986 {
987 *length = 0;
988 }
989
990 if (context->getClientMajorVersion() < 3)
991 {
992 context->handleError(
993 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
994 return false;
995 }
996
997 if (!context->isSampler(sampler))
998 {
999 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
1000 return false;
1001 }
1002
1003 switch (pname)
1004 {
1005 case GL_TEXTURE_WRAP_S:
1006 case GL_TEXTURE_WRAP_T:
1007 case GL_TEXTURE_WRAP_R:
1008 case GL_TEXTURE_MIN_FILTER:
1009 case GL_TEXTURE_MAG_FILTER:
1010 case GL_TEXTURE_MIN_LOD:
1011 case GL_TEXTURE_MAX_LOD:
1012 case GL_TEXTURE_COMPARE_MODE:
1013 case GL_TEXTURE_COMPARE_FUNC:
1014 break;
1015
Geoff Lang81c6b572016-10-19 14:07:52 -07001016 case GL_TEXTURE_SRGB_DECODE_EXT:
1017 if (!context->getExtensions().textureSRGBDecode)
1018 {
1019 context->handleError(
1020 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
1021 return false;
1022 }
1023 break;
1024
Geoff Langc1984ed2016-10-07 12:41:00 -04001025 default:
1026 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1027 return false;
1028 }
1029
1030 if (length)
1031 {
1032 *length = 1;
1033 }
1034 return true;
1035}
1036
Geoff Lang0b031062016-10-13 14:30:04 -04001037bool ValidateGetVertexAttribBase(Context *context,
1038 GLuint index,
1039 GLenum pname,
1040 GLsizei *length,
1041 bool pointer,
1042 bool pureIntegerEntryPoint)
1043{
1044 if (length)
1045 {
1046 *length = 0;
1047 }
1048
1049 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1050 {
1051 context->handleError(
1052 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1053 return false;
1054 }
1055
1056 if (index >= context->getCaps().maxVertexAttributes)
1057 {
1058 context->handleError(Error(
1059 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1060 return false;
1061 }
1062
1063 if (pointer)
1064 {
1065 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1066 {
1067 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1068 return false;
1069 }
1070 }
1071 else
1072 {
1073 switch (pname)
1074 {
1075 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1076 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1077 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1078 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1079 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1080 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1081 case GL_CURRENT_VERTEX_ATTRIB:
1082 break;
1083
1084 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1085 static_assert(
1086 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1087 "ANGLE extension enums not equal to GL enums.");
1088 if (context->getClientMajorVersion() < 3 &&
1089 !context->getExtensions().instancedArrays)
1090 {
1091 context->handleError(Error(GL_INVALID_ENUM,
1092 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1093 "3.0 or GL_ANGLE_instanced_arrays."));
1094 return false;
1095 }
1096 break;
1097
1098 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1099 if (context->getClientMajorVersion() < 3)
1100 {
1101 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1102 return false;
1103 }
1104 break;
1105
1106 default:
1107 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1108 return false;
1109 }
1110 }
1111
1112 if (length)
1113 {
1114 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1115 {
1116 *length = 4;
1117 }
1118 else
1119 {
1120 *length = 1;
1121 }
1122 }
1123
1124 return true;
1125}
1126
Geoff Lang6899b872016-10-14 11:30:13 -04001127bool ValidateGetActiveUniformBlockivBase(Context *context,
1128 GLuint program,
1129 GLuint uniformBlockIndex,
1130 GLenum pname,
1131 GLsizei *length)
1132{
1133 if (length)
1134 {
1135 *length = 0;
1136 }
1137
1138 if (context->getClientMajorVersion() < 3)
1139 {
1140 context->handleError(
1141 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1142 return false;
1143 }
1144
1145 Program *programObject = GetValidProgram(context, program);
1146 if (!programObject)
1147 {
1148 return false;
1149 }
1150
1151 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1152 {
1153 context->handleError(
1154 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1155 return false;
1156 }
1157
1158 switch (pname)
1159 {
1160 case GL_UNIFORM_BLOCK_BINDING:
1161 case GL_UNIFORM_BLOCK_DATA_SIZE:
1162 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1163 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1164 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1165 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1166 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1167 break;
1168
1169 default:
1170 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1171 return false;
1172 }
1173
1174 if (length)
1175 {
1176 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1177 {
1178 const UniformBlock &uniformBlock =
1179 programObject->getUniformBlockByIndex(uniformBlockIndex);
1180 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1181 }
1182 else
1183 {
1184 *length = 1;
1185 }
1186 }
1187
1188 return true;
1189}
1190
Geoff Langebebe1c2016-10-14 12:01:31 -04001191bool ValidateGetBufferParameterBase(ValidationContext *context,
1192 GLenum target,
1193 GLenum pname,
1194 bool pointerVersion,
1195 GLsizei *numParams)
1196{
1197 if (numParams)
1198 {
1199 *numParams = 0;
1200 }
1201
1202 if (!ValidBufferTarget(context, target))
1203 {
1204 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1205 return false;
1206 }
1207
1208 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1209 if (!buffer)
1210 {
1211 // A null buffer means that "0" is bound to the requested buffer target
1212 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1213 return false;
1214 }
1215
1216 const Extensions &extensions = context->getExtensions();
1217
1218 switch (pname)
1219 {
1220 case GL_BUFFER_USAGE:
1221 case GL_BUFFER_SIZE:
1222 break;
1223
1224 case GL_BUFFER_ACCESS_OES:
1225 if (!extensions.mapBuffer)
1226 {
1227 context->handleError(
1228 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
1229 return false;
1230 }
1231 break;
1232
1233 case GL_BUFFER_MAPPED:
1234 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1235 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1236 !extensions.mapBufferRange)
1237 {
1238 context->handleError(Error(
1239 GL_INVALID_ENUM,
1240 "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
1241 return false;
1242 }
1243 break;
1244
1245 case GL_BUFFER_MAP_POINTER:
1246 if (!pointerVersion)
1247 {
1248 context->handleError(
1249 Error(GL_INVALID_ENUM,
1250 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1251 return false;
1252 }
1253 break;
1254
1255 case GL_BUFFER_ACCESS_FLAGS:
1256 case GL_BUFFER_MAP_OFFSET:
1257 case GL_BUFFER_MAP_LENGTH:
1258 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1259 {
1260 context->handleError(Error(
1261 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1262 return false;
1263 }
1264 break;
1265
1266 default:
1267 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1268 return false;
1269 }
1270
1271 // All buffer parameter queries return one value.
1272 if (numParams)
1273 {
1274 *numParams = 1;
1275 }
1276
1277 return true;
1278}
1279
Geoff Lang0a9661f2016-10-20 10:59:20 -07001280bool ValidateGetInternalFormativBase(Context *context,
1281 GLenum target,
1282 GLenum internalformat,
1283 GLenum pname,
1284 GLsizei bufSize,
1285 GLsizei *numParams)
1286{
1287 if (numParams)
1288 {
1289 *numParams = 0;
1290 }
1291
1292 if (context->getClientMajorVersion() < 3)
1293 {
1294 context->handleError(
1295 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1296 return false;
1297 }
1298
1299 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1300 if (!formatCaps.renderable)
1301 {
1302 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1303 return false;
1304 }
1305
1306 switch (target)
1307 {
1308 case GL_RENDERBUFFER:
1309 break;
1310
1311 default:
1312 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1313 return false;
1314 }
1315
1316 if (bufSize < 0)
1317 {
1318 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1319 return false;
1320 }
1321
1322 GLsizei maxWriteParams = 0;
1323 switch (pname)
1324 {
1325 case GL_NUM_SAMPLE_COUNTS:
1326 maxWriteParams = 1;
1327 break;
1328
1329 case GL_SAMPLES:
1330 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1331 break;
1332
1333 default:
1334 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1335 return false;
1336 }
1337
1338 if (numParams)
1339 {
1340 // glGetInternalFormativ will not overflow bufSize
1341 *numParams = std::min(bufSize, maxWriteParams);
1342 }
1343
1344 return true;
1345}
1346
Geoff Langf41a7152016-09-19 15:11:17 -04001347} // anonymous namespace
1348
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001349bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001350{
Jamie Madilld7460c72014-01-21 16:38:14 -05001351 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001352 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001353 case GL_TEXTURE_2D:
1354 case GL_TEXTURE_CUBE_MAP:
1355 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001356
He Yunchaoced53ae2016-11-29 15:00:51 +08001357 case GL_TEXTURE_3D:
1358 case GL_TEXTURE_2D_ARRAY:
1359 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001360
He Yunchaoced53ae2016-11-29 15:00:51 +08001361 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001362 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001363
He Yunchaoced53ae2016-11-29 15:00:51 +08001364 default:
1365 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001366 }
Jamie Madill35d15012013-10-07 10:46:37 -04001367}
1368
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001369bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1370{
1371 switch (target)
1372 {
1373 case GL_TEXTURE_2D:
1374 case GL_TEXTURE_CUBE_MAP:
1375 return true;
1376
1377 default:
1378 return false;
1379 }
1380}
1381
1382bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1383{
1384 switch (target)
1385 {
1386 case GL_TEXTURE_3D:
1387 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001388 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001389
1390 default:
1391 return false;
1392 }
1393}
1394
Ian Ewellbda75592016-04-18 17:25:54 -04001395// Most texture GL calls are not compatible with external textures, so we have a separate validation
1396// function for use in the GL calls that do
1397bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1398{
1399 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1400 (context->getExtensions().eglImageExternal ||
1401 context->getExtensions().eglStreamConsumerExternal);
1402}
1403
Shannon Woods4dfed832014-03-17 20:03:39 -04001404// This function differs from ValidTextureTarget in that the target must be
1405// usable as the destination of a 2D operation-- so a cube face is valid, but
1406// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001407// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001408bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001409{
1410 switch (target)
1411 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001412 case GL_TEXTURE_2D:
1413 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1414 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1415 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1416 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1417 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1418 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1419 return true;
1420 default:
1421 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001422 }
1423}
1424
1425bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1426{
1427 switch (target)
1428 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001429 case GL_TEXTURE_3D:
1430 case GL_TEXTURE_2D_ARRAY:
1431 return true;
1432 default:
1433 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001434 }
1435}
1436
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001437bool ValidFramebufferTarget(GLenum target)
1438{
He Yunchaoced53ae2016-11-29 15:00:51 +08001439 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1440 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001441 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001442
1443 switch (target)
1444 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001445 case GL_FRAMEBUFFER:
1446 return true;
1447 case GL_READ_FRAMEBUFFER:
1448 return true;
1449 case GL_DRAW_FRAMEBUFFER:
1450 return true;
1451 default:
1452 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001453 }
1454}
1455
Jamie Madill29639852016-09-02 15:00:09 -04001456bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001457{
1458 switch (target)
1459 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001460 case GL_ARRAY_BUFFER:
1461 case GL_ELEMENT_ARRAY_BUFFER:
1462 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001463
He Yunchaoced53ae2016-11-29 15:00:51 +08001464 case GL_PIXEL_PACK_BUFFER:
1465 case GL_PIXEL_UNPACK_BUFFER:
1466 return (context->getExtensions().pixelBufferObject ||
1467 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001468
He Yunchaoced53ae2016-11-29 15:00:51 +08001469 case GL_COPY_READ_BUFFER:
1470 case GL_COPY_WRITE_BUFFER:
1471 case GL_TRANSFORM_FEEDBACK_BUFFER:
1472 case GL_UNIFORM_BUFFER:
1473 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001474
He Yunchaoced53ae2016-11-29 15:00:51 +08001475 case GL_ATOMIC_COUNTER_BUFFER:
1476 case GL_SHADER_STORAGE_BUFFER:
1477 case GL_DRAW_INDIRECT_BUFFER:
1478 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001479 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001480
He Yunchaoced53ae2016-11-29 15:00:51 +08001481 default:
1482 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001483 }
1484}
1485
Jamie Madillc29968b2016-01-20 11:17:23 -05001486bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001487{
Jamie Madillc29968b2016-01-20 11:17:23 -05001488 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001489 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001490 switch (target)
1491 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001492 case GL_TEXTURE_2D:
1493 maxDimension = caps.max2DTextureSize;
1494 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001495 case GL_TEXTURE_CUBE_MAP:
1496 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1497 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1498 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1499 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1500 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1501 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1502 maxDimension = caps.maxCubeMapTextureSize;
1503 break;
1504 case GL_TEXTURE_3D:
1505 maxDimension = caps.max3DTextureSize;
1506 break;
1507 case GL_TEXTURE_2D_ARRAY:
1508 maxDimension = caps.max2DTextureSize;
1509 break;
1510 default:
1511 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001512 }
1513
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001514 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001515}
1516
Geoff Langcc507aa2016-12-12 10:09:52 -05001517bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001518 GLenum target,
1519 GLint level,
1520 GLsizei width,
1521 GLsizei height,
1522 GLsizei depth,
1523 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001524{
1525 if (level < 0 || width < 0 || height < 0 || depth < 0)
1526 {
1527 return false;
1528 }
1529
Austin Kinross08528e12015-10-07 16:24:40 -07001530 // TexSubImage parameters can be NPOT without textureNPOT extension,
1531 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001532 bool hasNPOTSupport =
1533 context->getExtensions().textureNPOT && context->getClientVersion() >= Version(3, 0);
1534 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001535 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001536 {
1537 return false;
1538 }
1539
1540 if (!ValidMipLevel(context, target, level))
1541 {
1542 return false;
1543 }
1544
1545 return true;
1546}
1547
Geoff Lang0d8b7242015-09-09 14:56:53 -04001548bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1549{
1550 // List of compressed format that require that the texture size is smaller than or a multiple of
1551 // the compressed block size.
1552 switch (internalFormat)
1553 {
1554 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1555 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1556 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1557 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001558 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001559 return true;
1560
1561 default:
1562 return false;
1563 }
1564}
1565
Jamie Madillc29968b2016-01-20 11:17:23 -05001566bool ValidCompressedImageSize(const ValidationContext *context,
1567 GLenum internalFormat,
1568 GLsizei width,
1569 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001570{
Geoff Lang5d601382014-07-22 15:14:06 -04001571 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1572 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001573 {
1574 return false;
1575 }
1576
Geoff Lang0d8b7242015-09-09 14:56:53 -04001577 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001578 {
1579 return false;
1580 }
1581
Geoff Lang0d8b7242015-09-09 14:56:53 -04001582 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1583 {
1584 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1585 width % formatInfo.compressedBlockWidth != 0) ||
1586 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1587 height % formatInfo.compressedBlockHeight != 0))
1588 {
1589 return false;
1590 }
1591 }
1592
Geoff Langd4f180b2013-09-24 13:57:44 -04001593 return true;
1594}
1595
Geoff Langff5b2d52016-09-07 11:32:23 -04001596bool ValidImageDataSize(ValidationContext *context,
1597 GLenum textureTarget,
1598 GLsizei width,
1599 GLsizei height,
1600 GLsizei depth,
1601 GLenum internalFormat,
1602 GLenum type,
1603 const GLvoid *pixels,
1604 GLsizei imageSize)
1605{
1606 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1607 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1608 {
1609 // Checks are not required
1610 return true;
1611 }
1612
1613 // ...the data would be unpacked from the buffer object such that the memory reads required
1614 // would exceed the data store size.
1615 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1616 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1617 const gl::Extents size(width, height, depth);
1618 const auto &unpack = context->getGLState().getUnpackState();
1619
1620 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1621 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1622 if (endByteOrErr.isError())
1623 {
1624 context->handleError(endByteOrErr.getError());
1625 return false;
1626 }
1627
1628 GLuint endByte = endByteOrErr.getResult();
1629
1630 if (pixelUnpackBuffer)
1631 {
1632 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1633 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1634 checkedEndByte += checkedOffset;
1635
1636 if (!checkedEndByte.IsValid() ||
1637 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1638 {
1639 // Overflow past the end of the buffer
1640 context->handleError(Error(GL_INVALID_OPERATION));
1641 return false;
1642 }
1643 }
1644 else
1645 {
1646 ASSERT(imageSize >= 0);
1647 if (pixels == nullptr && imageSize != 0)
1648 {
1649 context->handleError(
1650 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001651 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001652 }
1653
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001654 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001655 {
1656 context->handleError(
1657 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1658 return false;
1659 }
1660 }
1661
1662 return true;
1663}
1664
Geoff Lang37dde692014-01-31 16:34:54 -05001665bool ValidQueryType(const Context *context, GLenum queryType)
1666{
He Yunchaoced53ae2016-11-29 15:00:51 +08001667 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1668 "GL extension enums not equal.");
1669 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1670 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001671
1672 switch (queryType)
1673 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001674 case GL_ANY_SAMPLES_PASSED:
1675 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1676 return true;
1677 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1678 return (context->getClientMajorVersion() >= 3);
1679 case GL_TIME_ELAPSED_EXT:
1680 return context->getExtensions().disjointTimerQuery;
1681 case GL_COMMANDS_COMPLETED_CHROMIUM:
1682 return context->getExtensions().syncQuery;
1683 default:
1684 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001685 }
1686}
1687
Jamie Madillef300b12016-10-07 15:12:09 -04001688Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001689{
He Yunchaoced53ae2016-11-29 15:00:51 +08001690 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1691 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1692 // or program object and INVALID_OPERATION if the provided name identifies an object
1693 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001694
Dian Xiang769769a2015-09-09 15:20:08 -07001695 Program *validProgram = context->getProgram(id);
1696
1697 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001698 {
Dian Xiang769769a2015-09-09 15:20:08 -07001699 if (context->getShader(id))
1700 {
Jamie Madill437fa652016-05-03 15:13:24 -04001701 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001702 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1703 }
1704 else
1705 {
Jamie Madill437fa652016-05-03 15:13:24 -04001706 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001707 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001708 }
Dian Xiang769769a2015-09-09 15:20:08 -07001709
1710 return validProgram;
1711}
1712
Jamie Madillef300b12016-10-07 15:12:09 -04001713Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001714{
1715 // See ValidProgram for spec details.
1716
1717 Shader *validShader = context->getShader(id);
1718
1719 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001720 {
Dian Xiang769769a2015-09-09 15:20:08 -07001721 if (context->getProgram(id))
1722 {
Jamie Madill437fa652016-05-03 15:13:24 -04001723 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001724 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1725 }
1726 else
1727 {
Jamie Madill437fa652016-05-03 15:13:24 -04001728 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001729 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001730 }
Dian Xiang769769a2015-09-09 15:20:08 -07001731
1732 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001733}
1734
Geoff Langb1196682014-07-23 13:47:29 -04001735bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001736{
1737 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1738 {
1739 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1740
Geoff Langaae65a42014-05-26 12:43:44 -04001741 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001742 {
Jamie Madill437fa652016-05-03 15:13:24 -04001743 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001744 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001745 }
1746 }
1747 else
1748 {
1749 switch (attachment)
1750 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001751 case GL_DEPTH_ATTACHMENT:
1752 case GL_STENCIL_ATTACHMENT:
1753 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001754
He Yunchaoced53ae2016-11-29 15:00:51 +08001755 case GL_DEPTH_STENCIL_ATTACHMENT:
1756 if (!context->getExtensions().webglCompatibility &&
1757 context->getClientMajorVersion() < 3)
1758 {
1759 context->handleError(Error(GL_INVALID_ENUM));
1760 return false;
1761 }
1762 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001763
He Yunchaoced53ae2016-11-29 15:00:51 +08001764 default:
1765 context->handleError(Error(GL_INVALID_ENUM));
1766 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001767 }
1768 }
1769
1770 return true;
1771}
1772
He Yunchaoced53ae2016-11-29 15:00:51 +08001773bool ValidateRenderbufferStorageParametersBase(gl::Context *context,
1774 GLenum target,
1775 GLsizei samples,
1776 GLenum internalformat,
1777 GLsizei width,
1778 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001779{
1780 switch (target)
1781 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001782 case GL_RENDERBUFFER:
1783 break;
1784 default:
1785 context->handleError(Error(GL_INVALID_ENUM));
1786 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001787 }
1788
1789 if (width < 0 || height < 0 || samples < 0)
1790 {
Jamie Madill437fa652016-05-03 15:13:24 -04001791 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001792 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001793 }
1794
Geoff Langd87878e2014-09-19 15:42:59 -04001795 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1796 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001797 {
Jamie Madill437fa652016-05-03 15:13:24 -04001798 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001799 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001800 }
1801
1802 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1803 // 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 -08001804 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001805 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001806 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001807 {
Jamie Madill437fa652016-05-03 15:13:24 -04001808 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001809 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001810 }
1811
Geoff Langaae65a42014-05-26 12:43:44 -04001812 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001813 {
Jamie Madill437fa652016-05-03 15:13:24 -04001814 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001815 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001816 }
1817
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001818 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001819 if (handle == 0)
1820 {
Jamie Madill437fa652016-05-03 15:13:24 -04001821 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001822 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001823 }
1824
1825 return true;
1826}
1827
He Yunchaoced53ae2016-11-29 15:00:51 +08001828bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context,
1829 GLenum target,
1830 GLsizei samples,
1831 GLenum internalformat,
1832 GLsizei width,
1833 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -08001834{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001835 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001836
1837 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001838 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001839 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001840 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001841 {
Jamie Madill437fa652016-05-03 15:13:24 -04001842 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001843 return false;
1844 }
1845
1846 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1847 // the specified storage. This is different than ES 3.0 in which a sample number higher
1848 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001849 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001850 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001851 {
Geoff Langa4903b72015-03-02 16:02:48 -08001852 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1853 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1854 {
Jamie Madill437fa652016-05-03 15:13:24 -04001855 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001856 return false;
1857 }
Corentin Walleze0902642014-11-04 12:32:15 -08001858 }
1859
He Yunchaoced53ae2016-11-29 15:00:51 +08001860 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
1861 width, height);
Corentin Walleze0902642014-11-04 12:32:15 -08001862}
1863
He Yunchaoced53ae2016-11-29 15:00:51 +08001864bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1865 GLenum target,
1866 GLenum attachment,
1867 GLenum renderbuffertarget,
1868 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001869{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001870 if (!ValidFramebufferTarget(target))
1871 {
Jamie Madill437fa652016-05-03 15:13:24 -04001872 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001873 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001874 }
1875
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001876 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001877
Jamie Madill84115c92015-04-23 15:00:07 -04001878 ASSERT(framebuffer);
1879 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001880 {
Jamie Madill437fa652016-05-03 15:13:24 -04001881 context->handleError(
1882 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001883 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001884 }
1885
Jamie Madillb4472272014-07-03 10:38:55 -04001886 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001887 {
Jamie Madillb4472272014-07-03 10:38:55 -04001888 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001889 }
1890
Jamie Madillab9d82c2014-01-21 16:38:14 -05001891 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1892 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1893 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1894 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1895 if (renderbuffer != 0)
1896 {
1897 if (!context->getRenderbuffer(renderbuffer))
1898 {
Jamie Madill437fa652016-05-03 15:13:24 -04001899 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001900 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001901 }
1902 }
1903
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001904 return true;
1905}
1906
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001907bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001908 GLint srcX0,
1909 GLint srcY0,
1910 GLint srcX1,
1911 GLint srcY1,
1912 GLint dstX0,
1913 GLint dstY0,
1914 GLint dstX1,
1915 GLint dstY1,
1916 GLbitfield mask,
1917 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001918{
1919 switch (filter)
1920 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001921 case GL_NEAREST:
1922 break;
1923 case GL_LINEAR:
1924 break;
1925 default:
1926 context->handleError(Error(GL_INVALID_ENUM));
1927 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001928 }
1929
1930 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1931 {
Jamie Madill437fa652016-05-03 15:13:24 -04001932 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001933 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001934 }
1935
1936 if (mask == 0)
1937 {
1938 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1939 // buffers are copied.
1940 return false;
1941 }
1942
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001943 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1944 // color buffer, leaving only nearest being unfiltered from above
1945 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1946 {
Jamie Madill437fa652016-05-03 15:13:24 -04001947 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001948 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001949 }
1950
Jamie Madill51f40ec2016-06-15 14:06:00 -04001951 const auto &glState = context->getGLState();
1952 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1953 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001954
1955 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001956 {
Jamie Madill437fa652016-05-03 15:13:24 -04001957 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001958 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001959 }
1960
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001961 if (readFramebuffer->id() == drawFramebuffer->id())
1962 {
1963 context->handleError(Error(GL_INVALID_OPERATION));
1964 return false;
1965 }
1966
Jamie Madill51f40ec2016-06-15 14:06:00 -04001967 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001968 {
Jamie Madill437fa652016-05-03 15:13:24 -04001969 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001970 return false;
1971 }
1972
Jamie Madill51f40ec2016-06-15 14:06:00 -04001973 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001974 {
Jamie Madill437fa652016-05-03 15:13:24 -04001975 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001976 return false;
1977 }
1978
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001979 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001980 {
Jamie Madill437fa652016-05-03 15:13:24 -04001981 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001982 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001983 }
1984
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001985 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1986
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001987 if (mask & GL_COLOR_BUFFER_BIT)
1988 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001989 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1990 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001991 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001992
1993 if (readColorBuffer && drawColorBuffer)
1994 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001995 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001996
Geoff Langa15472a2015-08-11 11:48:03 -04001997 for (size_t drawbufferIdx = 0;
1998 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001999 {
Geoff Langa15472a2015-08-11 11:48:03 -04002000 const FramebufferAttachment *attachment =
2001 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2002 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002003 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002004 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002005
Geoff Langb2f3d052013-08-13 12:49:27 -04002006 // The GL ES 3.0.2 spec (pg 193) states that:
2007 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002008 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2009 // as well
2010 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2011 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002012 // Changes with EXT_color_buffer_float:
2013 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002014 GLenum readComponentType = readFormat.info->componentType;
2015 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002016 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002017 readComponentType == GL_SIGNED_NORMALIZED);
2018 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2019 drawComponentType == GL_SIGNED_NORMALIZED);
2020
2021 if (extensions.colorBufferFloat)
2022 {
2023 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2024 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2025
2026 if (readFixedOrFloat != drawFixedOrFloat)
2027 {
Jamie Madill437fa652016-05-03 15:13:24 -04002028 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002029 "If the read buffer contains fixed-point or "
2030 "floating-point values, the draw buffer "
2031 "must as well."));
2032 return false;
2033 }
2034 }
2035 else if (readFixedPoint != drawFixedPoint)
2036 {
Jamie Madill437fa652016-05-03 15:13:24 -04002037 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002038 "If the read buffer contains fixed-point "
2039 "values, the draw buffer must as well."));
2040 return false;
2041 }
2042
2043 if (readComponentType == GL_UNSIGNED_INT &&
2044 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002045 {
Jamie Madill437fa652016-05-03 15:13:24 -04002046 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002047 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002048 }
2049
Jamie Madill6163c752015-12-07 16:32:59 -05002050 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002051 {
Jamie Madill437fa652016-05-03 15:13:24 -04002052 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002053 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002054 }
2055
Jamie Madilla3944d42016-07-22 22:13:26 -04002056 if (readColorBuffer->getSamples() > 0 &&
2057 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002058 {
Jamie Madill437fa652016-05-03 15:13:24 -04002059 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002060 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002061 }
2062 }
2063 }
2064
Jamie Madilla3944d42016-07-22 22:13:26 -04002065 if ((readFormat.info->componentType == GL_INT ||
2066 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2067 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002068 {
Jamie Madill437fa652016-05-03 15:13:24 -04002069 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002070 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002071 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002072 }
2073 }
2074
He Yunchaoced53ae2016-11-29 15:00:51 +08002075 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002076 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2077 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002078 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002079 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002080 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002081 const gl::FramebufferAttachment *readBuffer =
2082 readFramebuffer->getAttachment(attachments[i]);
2083 const gl::FramebufferAttachment *drawBuffer =
2084 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002085
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002086 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002087 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002088 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002089 {
Jamie Madill437fa652016-05-03 15:13:24 -04002090 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002091 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002092 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002093
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002094 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002095 {
Jamie Madill437fa652016-05-03 15:13:24 -04002096 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002097 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002098 }
2099 }
2100 }
2101 }
2102
2103 return true;
2104}
2105
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002106bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002107 GLint x,
2108 GLint y,
2109 GLsizei width,
2110 GLsizei height,
2111 GLenum format,
2112 GLenum type,
2113 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002114{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002115 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2116}
2117
2118bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2119 GLint x,
2120 GLint y,
2121 GLsizei width,
2122 GLsizei height,
2123 GLenum format,
2124 GLenum type,
2125 GLsizei bufSize,
2126 GLsizei *length,
2127 GLvoid *pixels)
2128{
2129 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002130 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002131 return false;
2132 }
2133
Geoff Lang62fce5b2016-09-30 10:46:35 -04002134 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2135 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002136 {
Geoff Langb1196682014-07-23 13:47:29 -04002137 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002138 }
2139
Geoff Lang62fce5b2016-09-30 10:46:35 -04002140 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002141 {
Geoff Langb1196682014-07-23 13:47:29 -04002142 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002143 }
2144
Jamie Madillc29968b2016-01-20 11:17:23 -05002145 return true;
2146}
2147
2148bool ValidateReadnPixelsEXT(Context *context,
2149 GLint x,
2150 GLint y,
2151 GLsizei width,
2152 GLsizei height,
2153 GLenum format,
2154 GLenum type,
2155 GLsizei bufSize,
2156 GLvoid *pixels)
2157{
2158 if (bufSize < 0)
2159 {
Jamie Madill437fa652016-05-03 15:13:24 -04002160 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002161 return false;
2162 }
2163
Geoff Lang62fce5b2016-09-30 10:46:35 -04002164 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2165 pixels);
2166}
Jamie Madill26e91952014-03-05 15:01:27 -05002167
Geoff Lang62fce5b2016-09-30 10:46:35 -04002168bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2169 GLint x,
2170 GLint y,
2171 GLsizei width,
2172 GLsizei height,
2173 GLenum format,
2174 GLenum type,
2175 GLsizei bufSize,
2176 GLsizei *length,
2177 GLvoid *data)
2178{
2179 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002180 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002181 return false;
2182 }
2183
Geoff Lang62fce5b2016-09-30 10:46:35 -04002184 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002185 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002186 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002187 }
2188
Geoff Lang62fce5b2016-09-30 10:46:35 -04002189 if (!ValidateRobustBufferSize(context, bufSize, *length))
2190 {
2191 return false;
2192 }
2193
2194 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002195}
2196
Olli Etuaho41997e72016-03-10 13:38:39 +02002197bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002198{
2199 if (!context->getExtensions().occlusionQueryBoolean &&
2200 !context->getExtensions().disjointTimerQuery)
2201 {
Jamie Madill437fa652016-05-03 15:13:24 -04002202 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002203 return false;
2204 }
2205
Olli Etuaho41997e72016-03-10 13:38:39 +02002206 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002207}
2208
Olli Etuaho41997e72016-03-10 13:38:39 +02002209bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002210{
2211 if (!context->getExtensions().occlusionQueryBoolean &&
2212 !context->getExtensions().disjointTimerQuery)
2213 {
Jamie Madill437fa652016-05-03 15:13:24 -04002214 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002215 return false;
2216 }
2217
Olli Etuaho41997e72016-03-10 13:38:39 +02002218 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002219}
2220
2221bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002222{
2223 if (!ValidQueryType(context, target))
2224 {
Jamie Madill437fa652016-05-03 15:13:24 -04002225 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002226 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002227 }
2228
2229 if (id == 0)
2230 {
Jamie Madill437fa652016-05-03 15:13:24 -04002231 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002232 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002233 }
2234
2235 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2236 // of zero, if the active query object name for <target> is non-zero (for the
2237 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2238 // the active query for either target is non-zero), if <id> is the name of an
2239 // existing query object whose type does not match <target>, or if <id> is the
2240 // active query object name for any query type, the error INVALID_OPERATION is
2241 // generated.
2242
2243 // Ensure no other queries are active
2244 // NOTE: If other queries than occlusion are supported, we will need to check
2245 // separately that:
2246 // a) The query ID passed is not the current active query for any target/type
2247 // b) There are no active queries for the requested target (and in the case
2248 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2249 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002250
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002251 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002252 {
Jamie Madill437fa652016-05-03 15:13:24 -04002253 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002254 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002255 }
2256
2257 Query *queryObject = context->getQuery(id, true, target);
2258
2259 // check that name was obtained with glGenQueries
2260 if (!queryObject)
2261 {
Jamie Madill437fa652016-05-03 15:13:24 -04002262 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002263 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002264 }
2265
2266 // check for type mismatch
2267 if (queryObject->getType() != target)
2268 {
Jamie Madill437fa652016-05-03 15:13:24 -04002269 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002270 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002271 }
2272
2273 return true;
2274}
2275
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002276bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2277{
2278 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002279 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002280 {
Jamie Madill437fa652016-05-03 15:13:24 -04002281 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002282 return false;
2283 }
2284
2285 return ValidateBeginQueryBase(context, target, id);
2286}
2287
2288bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002289{
2290 if (!ValidQueryType(context, target))
2291 {
Jamie Madill437fa652016-05-03 15:13:24 -04002292 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002293 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002294 }
2295
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002296 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002297
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002298 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002299 {
Jamie Madill437fa652016-05-03 15:13:24 -04002300 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002301 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002302 }
2303
Jamie Madill45c785d2014-05-13 14:09:34 -04002304 return true;
2305}
2306
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002307bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2308{
2309 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002310 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002311 {
Jamie Madill437fa652016-05-03 15:13:24 -04002312 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002313 return false;
2314 }
2315
2316 return ValidateEndQueryBase(context, target);
2317}
2318
2319bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2320{
2321 if (!context->getExtensions().disjointTimerQuery)
2322 {
Jamie Madill437fa652016-05-03 15:13:24 -04002323 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002324 return false;
2325 }
2326
2327 if (target != GL_TIMESTAMP_EXT)
2328 {
Jamie Madill437fa652016-05-03 15:13:24 -04002329 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002330 return false;
2331 }
2332
2333 Query *queryObject = context->getQuery(id, true, target);
2334 if (queryObject == nullptr)
2335 {
Jamie Madill437fa652016-05-03 15:13:24 -04002336 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002337 return false;
2338 }
2339
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002340 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002341 {
Jamie Madill437fa652016-05-03 15:13:24 -04002342 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002343 return false;
2344 }
2345
2346 return true;
2347}
2348
Geoff Lang2186c382016-10-14 10:54:54 -04002349bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002350{
Geoff Lang2186c382016-10-14 10:54:54 -04002351 if (numParams)
2352 {
2353 *numParams = 0;
2354 }
2355
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002356 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2357 {
Jamie Madill437fa652016-05-03 15:13:24 -04002358 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002359 return false;
2360 }
2361
2362 switch (pname)
2363 {
2364 case GL_CURRENT_QUERY_EXT:
2365 if (target == GL_TIMESTAMP_EXT)
2366 {
Jamie Madill437fa652016-05-03 15:13:24 -04002367 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002368 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2369 return false;
2370 }
2371 break;
2372 case GL_QUERY_COUNTER_BITS_EXT:
2373 if (!context->getExtensions().disjointTimerQuery ||
2374 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2375 {
Jamie Madill437fa652016-05-03 15:13:24 -04002376 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002377 return false;
2378 }
2379 break;
2380 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002381 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002382 return false;
2383 }
2384
Geoff Lang2186c382016-10-14 10:54:54 -04002385 if (numParams)
2386 {
2387 // All queries return only one value
2388 *numParams = 1;
2389 }
2390
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002391 return true;
2392}
2393
2394bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2395{
2396 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002397 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002398 {
Jamie Madill437fa652016-05-03 15:13:24 -04002399 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002400 return false;
2401 }
2402
Geoff Lang2186c382016-10-14 10:54:54 -04002403 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002404}
2405
Geoff Lang2186c382016-10-14 10:54:54 -04002406bool ValidateGetQueryivRobustANGLE(Context *context,
2407 GLenum target,
2408 GLenum pname,
2409 GLsizei bufSize,
2410 GLsizei *length,
2411 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002412{
Geoff Lang2186c382016-10-14 10:54:54 -04002413 if (!ValidateRobustEntryPoint(context, bufSize))
2414 {
2415 return false;
2416 }
2417
2418 if (!ValidateGetQueryivBase(context, target, pname, length))
2419 {
2420 return false;
2421 }
2422
2423 if (!ValidateRobustBufferSize(context, bufSize, *length))
2424 {
2425 return false;
2426 }
2427
2428 return true;
2429}
2430
2431bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2432{
2433 if (numParams)
2434 {
2435 *numParams = 0;
2436 }
2437
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002438 Query *queryObject = context->getQuery(id, false, GL_NONE);
2439
2440 if (!queryObject)
2441 {
Jamie Madill437fa652016-05-03 15:13:24 -04002442 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002443 return false;
2444 }
2445
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002446 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002447 {
Jamie Madill437fa652016-05-03 15:13:24 -04002448 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002449 return false;
2450 }
2451
2452 switch (pname)
2453 {
2454 case GL_QUERY_RESULT_EXT:
2455 case GL_QUERY_RESULT_AVAILABLE_EXT:
2456 break;
2457
2458 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002459 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002460 return false;
2461 }
2462
Geoff Lang2186c382016-10-14 10:54:54 -04002463 if (numParams)
2464 {
2465 *numParams = 1;
2466 }
2467
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002468 return true;
2469}
2470
2471bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2472{
2473 if (!context->getExtensions().disjointTimerQuery)
2474 {
Jamie Madill437fa652016-05-03 15:13:24 -04002475 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002476 return false;
2477 }
Geoff Lang2186c382016-10-14 10:54:54 -04002478 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2479}
2480
2481bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2482 GLuint id,
2483 GLenum pname,
2484 GLsizei bufSize,
2485 GLsizei *length,
2486 GLint *params)
2487{
2488 if (!context->getExtensions().disjointTimerQuery)
2489 {
2490 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2491 return false;
2492 }
2493
2494 if (!ValidateRobustEntryPoint(context, bufSize))
2495 {
2496 return false;
2497 }
2498
2499 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2500 {
2501 return false;
2502 }
2503
2504 if (!ValidateRobustBufferSize(context, bufSize, *length))
2505 {
2506 return false;
2507 }
2508
2509 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002510}
2511
2512bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2513{
2514 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002515 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002516 {
Jamie Madill437fa652016-05-03 15:13:24 -04002517 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002518 return false;
2519 }
Geoff Lang2186c382016-10-14 10:54:54 -04002520 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2521}
2522
2523bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2524 GLuint id,
2525 GLenum pname,
2526 GLsizei bufSize,
2527 GLsizei *length,
2528 GLuint *params)
2529{
2530 if (!context->getExtensions().disjointTimerQuery &&
2531 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2532 {
2533 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2534 return false;
2535 }
2536
2537 if (!ValidateRobustEntryPoint(context, bufSize))
2538 {
2539 return false;
2540 }
2541
2542 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2543 {
2544 return false;
2545 }
2546
2547 if (!ValidateRobustBufferSize(context, bufSize, *length))
2548 {
2549 return false;
2550 }
2551
2552 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002553}
2554
2555bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2556{
2557 if (!context->getExtensions().disjointTimerQuery)
2558 {
Jamie Madill437fa652016-05-03 15:13:24 -04002559 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002560 return false;
2561 }
Geoff Lang2186c382016-10-14 10:54:54 -04002562 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2563}
2564
2565bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2566 GLuint id,
2567 GLenum pname,
2568 GLsizei bufSize,
2569 GLsizei *length,
2570 GLint64 *params)
2571{
2572 if (!context->getExtensions().disjointTimerQuery)
2573 {
2574 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2575 return false;
2576 }
2577
2578 if (!ValidateRobustEntryPoint(context, bufSize))
2579 {
2580 return false;
2581 }
2582
2583 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2584 {
2585 return false;
2586 }
2587
2588 if (!ValidateRobustBufferSize(context, bufSize, *length))
2589 {
2590 return false;
2591 }
2592
2593 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002594}
2595
2596bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2597{
2598 if (!context->getExtensions().disjointTimerQuery)
2599 {
Jamie Madill437fa652016-05-03 15:13:24 -04002600 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002601 return false;
2602 }
Geoff Lang2186c382016-10-14 10:54:54 -04002603 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2604}
2605
2606bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2607 GLuint id,
2608 GLenum pname,
2609 GLsizei bufSize,
2610 GLsizei *length,
2611 GLuint64 *params)
2612{
2613 if (!context->getExtensions().disjointTimerQuery)
2614 {
2615 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2616 return false;
2617 }
2618
2619 if (!ValidateRobustEntryPoint(context, bufSize))
2620 {
2621 return false;
2622 }
2623
2624 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2625 {
2626 return false;
2627 }
2628
2629 if (!ValidateRobustBufferSize(context, bufSize, *length))
2630 {
2631 return false;
2632 }
2633
2634 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002635}
2636
Jamie Madill62d31cb2015-09-11 13:25:51 -04002637static bool ValidateUniformCommonBase(gl::Context *context,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002638 gl::Program *program,
Jamie Madill62d31cb2015-09-11 13:25:51 -04002639 GLenum targetUniformType,
2640 GLint location,
2641 GLsizei count,
2642 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002643{
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002644 // TODO(Jiajia): Add image uniform check in future.
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002645 if (count < 0)
2646 {
Jamie Madill437fa652016-05-03 15:13:24 -04002647 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002648 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002649 }
2650
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002651 if (!program || !program->isLinked())
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002652 {
Jamie Madill437fa652016-05-03 15:13:24 -04002653 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002654 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002655 }
2656
Geoff Langd8605522016-04-13 10:19:12 -04002657 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002658 {
2659 // Silently ignore the uniform command
2660 return false;
2661 }
2662
Geoff Lang7dd2e102014-11-10 15:19:26 -05002663 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002664 {
Jamie Madill437fa652016-05-03 15:13:24 -04002665 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002666 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002667 }
2668
Jamie Madill62d31cb2015-09-11 13:25:51 -04002669 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002670
2671 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002672 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002673 {
Jamie Madill437fa652016-05-03 15:13:24 -04002674 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002675 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002676 }
2677
Jamie Madill62d31cb2015-09-11 13:25:51 -04002678 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002679 return true;
2680}
2681
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002682bool ValidateProgramUniform(gl::Context *context,
2683 GLenum uniformType,
2684 GLuint program,
2685 GLint location,
2686 GLsizei count)
2687{
2688 // Check for ES31 program uniform entry points
2689 if (context->getClientVersion() < Version(3, 1))
2690 {
2691 context->handleError(Error(GL_INVALID_OPERATION));
2692 return false;
2693 }
2694
2695 const LinkedUniform *uniform = nullptr;
2696 gl::Program *programObject = GetValidProgram(context, program);
2697 if (!ValidateUniformCommonBase(context, programObject, uniformType, location, count, &uniform))
2698 {
2699 return false;
2700 }
2701
2702 GLenum targetBoolType = VariableBoolVectorType(uniformType);
2703 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
2704 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2705 {
2706 context->handleError(Error(GL_INVALID_OPERATION));
2707 return false;
2708 }
2709
2710 return true;
2711}
2712
2713bool ValidateProgramUniformMatrix(gl::Context *context,
2714 GLenum matrixType,
2715 GLuint program,
2716 GLint location,
2717 GLsizei count,
2718 GLboolean transpose)
2719{
2720 // Check for ES31 program uniform entry points
2721 if (context->getClientVersion() < Version(3, 1))
2722 {
2723 context->handleError(Error(GL_INVALID_OPERATION));
2724 return false;
2725 }
2726
2727 const LinkedUniform *uniform = nullptr;
2728 gl::Program *programObject = GetValidProgram(context, program);
2729 if (!ValidateUniformCommonBase(context, programObject, matrixType, location, count, &uniform))
2730 {
2731 return false;
2732 }
2733
2734 if (uniform->type != matrixType)
2735 {
2736 context->handleError(Error(GL_INVALID_OPERATION));
2737 return false;
2738 }
2739
2740 return true;
2741}
2742
Jamie Madillaa981bd2014-05-20 10:55:55 -04002743bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2744{
2745 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002746 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2747 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002748 {
Jamie Madill437fa652016-05-03 15:13:24 -04002749 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002750 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002751 }
2752
Jamie Madill62d31cb2015-09-11 13:25:51 -04002753 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002754 gl::Program *program = context->getGLState().getProgram();
2755 if (!ValidateUniformCommonBase(context, program, uniformType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002756 {
2757 return false;
2758 }
2759
He Yunchaoced53ae2016-11-29 15:00:51 +08002760 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002761 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002762 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2763 {
Jamie Madill437fa652016-05-03 15:13:24 -04002764 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002765 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002766 }
2767
2768 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002769}
2770
He Yunchaoced53ae2016-11-29 15:00:51 +08002771bool ValidateUniformMatrix(gl::Context *context,
2772 GLenum matrixType,
2773 GLint location,
2774 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002775 GLboolean transpose)
2776{
2777 // Check for ES3 uniform entry points
2778 int rows = VariableRowCount(matrixType);
2779 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002780 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002781 {
Jamie Madill437fa652016-05-03 15:13:24 -04002782 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002783 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002784 }
2785
Martin Radev1be913c2016-07-11 17:59:16 +03002786 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002787 {
Jamie Madill437fa652016-05-03 15:13:24 -04002788 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002789 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002790 }
2791
Jamie Madill62d31cb2015-09-11 13:25:51 -04002792 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002793 gl::Program *program = context->getGLState().getProgram();
2794 if (!ValidateUniformCommonBase(context, program, matrixType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002795 {
2796 return false;
2797 }
2798
2799 if (uniform->type != matrixType)
2800 {
Jamie Madill437fa652016-05-03 15:13:24 -04002801 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002802 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002803 }
2804
2805 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002806}
2807
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002808bool ValidateStateQuery(ValidationContext *context,
2809 GLenum pname,
2810 GLenum *nativeType,
2811 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002812{
2813 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2814 {
Jamie Madill437fa652016-05-03 15:13:24 -04002815 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002816 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002817 }
2818
Jamie Madill0af26e12015-03-05 19:54:33 -05002819 const Caps &caps = context->getCaps();
2820
Jamie Madill893ab082014-05-16 16:56:10 -04002821 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2822 {
2823 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2824
Jamie Madill0af26e12015-03-05 19:54:33 -05002825 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002826 {
Jamie Madill437fa652016-05-03 15:13:24 -04002827 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002828 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002829 }
2830 }
2831
2832 switch (pname)
2833 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002834 case GL_TEXTURE_BINDING_2D:
2835 case GL_TEXTURE_BINDING_CUBE_MAP:
2836 case GL_TEXTURE_BINDING_3D:
2837 case GL_TEXTURE_BINDING_2D_ARRAY:
2838 break;
2839 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2840 if (!context->getExtensions().eglStreamConsumerExternal &&
2841 !context->getExtensions().eglImageExternal)
2842 {
2843 context->handleError(Error(GL_INVALID_ENUM,
2844 "Neither NV_EGL_stream_consumer_external nor "
2845 "GL_OES_EGL_image_external extensions enabled"));
2846 return false;
2847 }
2848 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002849
He Yunchaoced53ae2016-11-29 15:00:51 +08002850 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2851 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002852 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002853 if (context->getGLState().getReadFramebuffer()->checkStatus(
2854 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002855 {
Jamie Madill437fa652016-05-03 15:13:24 -04002856 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002857 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002858 }
2859
Jamie Madill51f40ec2016-06-15 14:06:00 -04002860 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2861 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002862
2863 if (framebuffer->getReadBufferState() == GL_NONE)
2864 {
2865 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2866 return false;
2867 }
2868
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002869 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002870 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002871 {
Jamie Madill437fa652016-05-03 15:13:24 -04002872 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002873 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002874 }
2875 }
2876 break;
2877
He Yunchaoced53ae2016-11-29 15:00:51 +08002878 default:
2879 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002880 }
2881
2882 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002883 if (*numParams == 0)
2884 {
2885 return false;
2886 }
2887
2888 return true;
2889}
2890
2891bool ValidateRobustStateQuery(ValidationContext *context,
2892 GLenum pname,
2893 GLsizei bufSize,
2894 GLenum *nativeType,
2895 unsigned int *numParams)
2896{
2897 if (!ValidateRobustEntryPoint(context, bufSize))
2898 {
2899 return false;
2900 }
2901
2902 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2903 {
2904 return false;
2905 }
2906
2907 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002908 {
2909 return false;
2910 }
2911
2912 return true;
2913}
2914
Jamie Madillc29968b2016-01-20 11:17:23 -05002915bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2916 GLenum target,
2917 GLint level,
2918 GLenum internalformat,
2919 bool isSubImage,
2920 GLint xoffset,
2921 GLint yoffset,
2922 GLint zoffset,
2923 GLint x,
2924 GLint y,
2925 GLsizei width,
2926 GLsizei height,
2927 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002928 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002929{
Jamie Madill560a8d82014-05-21 13:06:20 -04002930 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2931 {
Jamie Madill437fa652016-05-03 15:13:24 -04002932 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002933 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002934 }
2935
He Yunchaoced53ae2016-11-29 15:00:51 +08002936 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2937 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002938 {
Jamie Madill437fa652016-05-03 15:13:24 -04002939 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002940 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002941 }
2942
2943 if (border != 0)
2944 {
Jamie Madill437fa652016-05-03 15:13:24 -04002945 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002946 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002947 }
2948
2949 if (!ValidMipLevel(context, target, level))
2950 {
Jamie Madill437fa652016-05-03 15:13:24 -04002951 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002952 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002953 }
2954
Jamie Madill51f40ec2016-06-15 14:06:00 -04002955 const auto &state = context->getGLState();
2956 auto readFramebuffer = state.getReadFramebuffer();
2957 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002958 {
Jamie Madill437fa652016-05-03 15:13:24 -04002959 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002960 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002961 }
2962
Jamie Madill51f40ec2016-06-15 14:06:00 -04002963 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002964 {
Jamie Madill437fa652016-05-03 15:13:24 -04002965 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002966 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002967 }
2968
Martin Radev138064f2016-07-15 12:03:41 +03002969 if (readFramebuffer->getReadBufferState() == GL_NONE)
2970 {
2971 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2972 return false;
2973 }
2974
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002975 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2976 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
2977 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
2978 // situation is an application error that would lead to a crash in ANGLE.
2979 if (readFramebuffer->getReadColorbuffer() == nullptr)
2980 {
2981 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
2982 return false;
2983 }
2984
Geoff Langaae65a42014-05-26 12:43:44 -04002985 const gl::Caps &caps = context->getCaps();
2986
Geoff Langaae65a42014-05-26 12:43:44 -04002987 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002988 switch (target)
2989 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002990 case GL_TEXTURE_2D:
2991 maxDimension = caps.max2DTextureSize;
2992 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002993
He Yunchaoced53ae2016-11-29 15:00:51 +08002994 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2995 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2996 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2997 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2998 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2999 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3000 maxDimension = caps.maxCubeMapTextureSize;
3001 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003002
He Yunchaoced53ae2016-11-29 15:00:51 +08003003 case GL_TEXTURE_2D_ARRAY:
3004 maxDimension = caps.max2DTextureSize;
3005 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003006
He Yunchaoced53ae2016-11-29 15:00:51 +08003007 case GL_TEXTURE_3D:
3008 maxDimension = caps.max3DTextureSize;
3009 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003010
He Yunchaoced53ae2016-11-29 15:00:51 +08003011 default:
3012 context->handleError(Error(GL_INVALID_ENUM));
3013 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003014 }
3015
Jamie Madillc29968b2016-01-20 11:17:23 -05003016 gl::Texture *texture =
3017 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003018 if (!texture)
3019 {
Jamie Madill437fa652016-05-03 15:13:24 -04003020 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003021 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003022 }
3023
Geoff Lang69cce582015-09-17 13:20:36 -04003024 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003025 {
Jamie Madill437fa652016-05-03 15:13:24 -04003026 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003027 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003028 }
3029
Geoff Lang5d601382014-07-22 15:14:06 -04003030 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3031
3032 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003033 {
Jamie Madill437fa652016-05-03 15:13:24 -04003034 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003035 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003036 }
3037
Geoff Langa9be0dc2014-12-17 12:34:40 -05003038 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003039 {
Jamie Madill437fa652016-05-03 15:13:24 -04003040 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003041 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003042 }
3043
3044 if (isSubImage)
3045 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003046 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3047 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3048 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003049 {
Jamie Madill437fa652016-05-03 15:13:24 -04003050 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003051 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003052 }
3053 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003054 else
3055 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003056 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003057 {
Jamie Madill437fa652016-05-03 15:13:24 -04003058 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003059 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003060 }
3061
Geoff Langeb66a6e2016-10-31 13:06:12 -04003062 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003063 {
Jamie Madill437fa652016-05-03 15:13:24 -04003064 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003065 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003066 }
3067
3068 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003069 if (static_cast<int>(width) > maxLevelDimension ||
3070 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003071 {
Jamie Madill437fa652016-05-03 15:13:24 -04003072 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003073 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003074 }
3075 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003076
Jamie Madill0c8abca2016-07-22 20:21:26 -04003077 if (textureFormatOut)
3078 {
3079 *textureFormatOut = texture->getFormat(target, level);
3080 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003081 return true;
3082}
3083
Jiajia Qind9671222016-11-29 16:30:31 +08003084bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003085{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003086 switch (mode)
3087 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003088 case GL_POINTS:
3089 case GL_LINES:
3090 case GL_LINE_LOOP:
3091 case GL_LINE_STRIP:
3092 case GL_TRIANGLES:
3093 case GL_TRIANGLE_STRIP:
3094 case GL_TRIANGLE_FAN:
3095 break;
3096 default:
3097 context->handleError(Error(GL_INVALID_ENUM));
3098 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003099 }
3100
Jamie Madill250d33f2014-06-06 17:09:03 -04003101 if (count < 0)
3102 {
Jamie Madill437fa652016-05-03 15:13:24 -04003103 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003104 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003105 }
3106
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003107 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003108
Jamie Madill250d33f2014-06-06 17:09:03 -04003109 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003110 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003111 {
Jamie Madill437fa652016-05-03 15:13:24 -04003112 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003113 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003114 }
3115
Jamie Madill51f40ec2016-06-15 14:06:00 -04003116 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003117 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3118 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003119 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003120 const FramebufferAttachment *dsAttachment =
3121 framebuffer->getStencilOrDepthStencilAttachment();
3122 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003123 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003124 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003125
3126 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3127 bool differentWritemasks =
3128 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3129 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3130 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3131 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3132
3133 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003134 {
3135 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3136 // Section 6.10 of the WebGL 1.0 spec
He Yunchaoced53ae2016-11-29 15:00:51 +08003137 ERR("This ANGLE implementation does not support separate front/back stencil "
Geoff Lang3a86ad32015-09-01 11:47:05 -04003138 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04003139 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003140 return false;
3141 }
Jamie Madillac528012014-06-20 13:21:23 -04003142 }
3143
Jamie Madill51f40ec2016-06-15 14:06:00 -04003144 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003145 {
Jamie Madill437fa652016-05-03 15:13:24 -04003146 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003147 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003148 }
3149
Geoff Lang7dd2e102014-11-10 15:19:26 -05003150 gl::Program *program = state.getProgram();
3151 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003152 {
Jamie Madill437fa652016-05-03 15:13:24 -04003153 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003154 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003155 }
3156
Geoff Lang7dd2e102014-11-10 15:19:26 -05003157 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003158 {
Jamie Madill437fa652016-05-03 15:13:24 -04003159 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003160 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003161 }
3162
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003163 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003164 for (unsigned int uniformBlockIndex = 0;
3165 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003166 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003167 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003168 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003169 const OffsetBindingPointer<Buffer> &uniformBuffer =
3170 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003171
Geoff Lang5d124a62015-09-15 13:03:27 -04003172 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003173 {
3174 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003175 context->handleError(
3176 Error(GL_INVALID_OPERATION,
3177 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003178 return false;
3179 }
3180
Geoff Lang5d124a62015-09-15 13:03:27 -04003181 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003182 if (uniformBufferSize == 0)
3183 {
3184 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003185 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003186 }
3187
Jamie Madill62d31cb2015-09-11 13:25:51 -04003188 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003189 {
3190 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003191 context->handleError(
3192 Error(GL_INVALID_OPERATION,
3193 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003194 return false;
3195 }
3196 }
3197
Jamie Madill250d33f2014-06-06 17:09:03 -04003198 // No-op if zero count
3199 return (count > 0);
3200}
3201
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003202bool ValidateDrawArrays(ValidationContext *context,
3203 GLenum mode,
3204 GLint first,
3205 GLsizei count,
3206 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003207{
Jamie Madillfd716582014-06-06 17:09:04 -04003208 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003209 {
Jamie Madill437fa652016-05-03 15:13:24 -04003210 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003211 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003212 }
3213
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003214 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003215 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003216 if (curTransformFeedback && curTransformFeedback->isActive() &&
3217 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003218 {
3219 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003220 // that does not match the current transform feedback object's draw mode (if transform
3221 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003222 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003223 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003224 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003225 }
3226
Jiajia Qind9671222016-11-29 16:30:31 +08003227 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003228 {
3229 return false;
3230 }
3231
Corentin Wallez71168a02016-12-19 15:11:18 -08003232 // Check the computation of maxVertex doesn't overflow.
3233 // - first < 0 or count < 0 have been checked as an error condition
3234 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3235 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3236 ASSERT(count > 0 && first >= 0);
3237 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3238 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003239 {
3240 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3241 return false;
3242 }
3243
Corentin Wallez71168a02016-12-19 15:11:18 -08003244 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003245 {
3246 return false;
3247 }
3248
3249 return true;
3250}
3251
He Yunchaoced53ae2016-11-29 15:00:51 +08003252bool ValidateDrawArraysInstanced(Context *context,
3253 GLenum mode,
3254 GLint first,
3255 GLsizei count,
3256 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003257{
3258 if (primcount < 0)
3259 {
Jamie Madill437fa652016-05-03 15:13:24 -04003260 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003261 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003262 }
3263
Jamie Madill2b976812014-08-25 15:47:49 -04003264 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003265 {
3266 return false;
3267 }
3268
3269 // No-op if zero primitive count
3270 return (primcount > 0);
3271}
3272
Geoff Lang87a93302014-09-16 13:29:43 -04003273static bool ValidateDrawInstancedANGLE(Context *context)
3274{
3275 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003276 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003277
Geoff Lang7dd2e102014-11-10 15:19:26 -05003278 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003279
3280 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003281 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003282 {
3283 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003284 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003285 {
3286 return true;
3287 }
3288 }
3289
Jamie Madill437fa652016-05-03 15:13:24 -04003290 context->handleError(Error(GL_INVALID_OPERATION,
3291 "ANGLE_instanced_arrays requires that at least one active attribute"
3292 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003293 return false;
3294}
3295
He Yunchaoced53ae2016-11-29 15:00:51 +08003296bool ValidateDrawArraysInstancedANGLE(Context *context,
3297 GLenum mode,
3298 GLint first,
3299 GLsizei count,
3300 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003301{
3302 if (!ValidateDrawInstancedANGLE(context))
3303 {
3304 return false;
3305 }
3306
3307 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3308}
3309
Jiajia Qind9671222016-11-29 16:30:31 +08003310bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003311{
Jamie Madill250d33f2014-06-06 17:09:03 -04003312 switch (type)
3313 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003314 case GL_UNSIGNED_BYTE:
3315 case GL_UNSIGNED_SHORT:
3316 break;
3317 case GL_UNSIGNED_INT:
3318 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3319 {
3320 context->handleError(Error(GL_INVALID_ENUM));
3321 return false;
3322 }
3323 break;
3324 default:
3325 context->handleError(Error(GL_INVALID_ENUM));
3326 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003327 }
3328
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003329 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003330
3331 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003332 if (curTransformFeedback && curTransformFeedback->isActive() &&
3333 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003334 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003335 // It is an invalid operation to call DrawElements, DrawRangeElements or
3336 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003337 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003338 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003339 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003340 }
3341
Jiajia Qind9671222016-11-29 16:30:31 +08003342 return true;
3343}
3344
3345bool ValidateDrawElements(ValidationContext *context,
3346 GLenum mode,
3347 GLsizei count,
3348 GLenum type,
3349 const GLvoid *indices,
3350 GLsizei primcount,
3351 IndexRange *indexRangeOut)
3352{
3353 if (!ValidateDrawElementsBase(context, type))
3354 return false;
3355
3356 const State &state = context->getGLState();
3357
Jamie Madill250d33f2014-06-06 17:09:03 -04003358 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003359 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003360 {
Jamie Madill437fa652016-05-03 15:13:24 -04003361 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003362 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003363 }
3364
He Yunchaoced53ae2016-11-29 15:00:51 +08003365 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003366 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003367
Jamie Madillae3000b2014-08-25 15:47:51 -04003368 if (elementArrayBuffer)
3369 {
3370 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3371
3372 GLint64 offset = reinterpret_cast<GLint64>(indices);
He Yunchaoced53ae2016-11-29 15:00:51 +08003373 GLint64 byteCount =
3374 static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count) + offset;
Jamie Madillae3000b2014-08-25 15:47:51 -04003375
3376 // check for integer overflows
3377 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3378 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3379 {
Jamie Madill437fa652016-05-03 15:13:24 -04003380 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003381 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003382 }
3383
3384 // Check for reading past the end of the bound buffer object
3385 if (byteCount > elementArrayBuffer->getSize())
3386 {
Jamie Madill437fa652016-05-03 15:13:24 -04003387 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003388 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003389 }
3390 }
Corentin Wallez327411e2016-12-09 11:09:17 -05003391 else if (context->getExtensions().webglCompatibility && count > 0)
3392 {
3393 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3394 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3395 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3396 context->handleError(
3397 Error(GL_INVALID_OPERATION, "There is no element array buffer bound and count > 0."));
3398 return false;
3399 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003400 else if (!indices)
3401 {
Corentin Wallez327411e2016-12-09 11:09:17 -05003402 // This is an application error that would normally result in a crash,
3403 // but we catch it and return an error
3404 context->handleError(
3405 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003406 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003407 }
3408
Jiajia Qind9671222016-11-29 16:30:31 +08003409 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003410 {
3411 return false;
3412 }
3413
Jamie Madill2b976812014-08-25 15:47:49 -04003414 // Use max index to validate if our vertex buffers are large enough for the pull.
3415 // TODO: offer fast path, with disabled index validation.
3416 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3417 if (elementArrayBuffer)
3418 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003419 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003420 Error error =
3421 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3422 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003423 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003424 {
Jamie Madill437fa652016-05-03 15:13:24 -04003425 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003426 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003427 }
3428 }
3429 else
3430 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003431 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003432 }
3433
Jamie Madille79b1e12015-11-04 16:36:37 -05003434 // If we use an index greater than our maximum supported index range, return an error.
3435 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3436 // return an error if possible here.
3437 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3438 {
Jamie Madill437fa652016-05-03 15:13:24 -04003439 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003440 return false;
3441 }
3442
Corentin Wallez92db6942016-12-09 13:10:36 -05003443 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3444 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003445 {
3446 return false;
3447 }
3448
Geoff Lang3edfe032015-09-04 16:38:24 -04003449 // No op if there are no real indices in the index data (all are primitive restart).
3450 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003451}
3452
Geoff Langb1196682014-07-23 13:47:29 -04003453bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003454 GLenum mode,
3455 GLsizei count,
3456 GLenum type,
3457 const GLvoid *indices,
3458 GLsizei primcount,
3459 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003460{
3461 if (primcount < 0)
3462 {
Jamie Madill437fa652016-05-03 15:13:24 -04003463 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003464 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003465 }
3466
Jamie Madill2b976812014-08-25 15:47:49 -04003467 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003468 {
3469 return false;
3470 }
3471
3472 // No-op zero primitive count
3473 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003474}
3475
Geoff Lang3edfe032015-09-04 16:38:24 -04003476bool ValidateDrawElementsInstancedANGLE(Context *context,
3477 GLenum mode,
3478 GLsizei count,
3479 GLenum type,
3480 const GLvoid *indices,
3481 GLsizei primcount,
3482 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003483{
3484 if (!ValidateDrawInstancedANGLE(context))
3485 {
3486 return false;
3487 }
3488
He Yunchaoced53ae2016-11-29 15:00:51 +08003489 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3490 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003491}
3492
He Yunchaoced53ae2016-11-29 15:00:51 +08003493bool ValidateFramebufferTextureBase(Context *context,
3494 GLenum target,
3495 GLenum attachment,
3496 GLuint texture,
3497 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003498{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003499 if (!ValidFramebufferTarget(target))
3500 {
Jamie Madill437fa652016-05-03 15:13:24 -04003501 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003502 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003503 }
3504
3505 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003506 {
3507 return false;
3508 }
3509
Jamie Madill55ec3b12014-07-03 10:38:57 -04003510 if (texture != 0)
3511 {
3512 gl::Texture *tex = context->getTexture(texture);
3513
3514 if (tex == NULL)
3515 {
Jamie Madill437fa652016-05-03 15:13:24 -04003516 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003517 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003518 }
3519
3520 if (level < 0)
3521 {
Jamie Madill437fa652016-05-03 15:13:24 -04003522 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003523 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003524 }
3525 }
3526
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003527 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003528 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003529
Jamie Madill84115c92015-04-23 15:00:07 -04003530 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003531 {
Jamie Madill437fa652016-05-03 15:13:24 -04003532 context->handleError(
3533 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003534 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003535 }
3536
3537 return true;
3538}
3539
He Yunchaoced53ae2016-11-29 15:00:51 +08003540bool ValidateFramebufferTexture2D(Context *context,
3541 GLenum target,
3542 GLenum attachment,
3543 GLenum textarget,
3544 GLuint texture,
3545 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003546{
He Yunchaoced53ae2016-11-29 15:00:51 +08003547 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3548 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003549 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3550 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003551 {
Jamie Madill437fa652016-05-03 15:13:24 -04003552 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003553 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003554 }
3555
3556 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003557 {
3558 return false;
3559 }
3560
Jamie Madill55ec3b12014-07-03 10:38:57 -04003561 if (texture != 0)
3562 {
3563 gl::Texture *tex = context->getTexture(texture);
3564 ASSERT(tex);
3565
Jamie Madill2a6564e2014-07-11 09:53:19 -04003566 const gl::Caps &caps = context->getCaps();
3567
Jamie Madill55ec3b12014-07-03 10:38:57 -04003568 switch (textarget)
3569 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003570 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003571 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003572 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003573 {
Jamie Madill437fa652016-05-03 15:13:24 -04003574 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003575 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003576 }
3577 if (tex->getTarget() != GL_TEXTURE_2D)
3578 {
Jamie Madill437fa652016-05-03 15:13:24 -04003579 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003580 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003581 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003582 }
3583 break;
3584
He Yunchaoced53ae2016-11-29 15:00:51 +08003585 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3586 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3587 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3588 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3589 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3590 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003591 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003592 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003593 {
Jamie Madill437fa652016-05-03 15:13:24 -04003594 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003595 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003596 }
3597 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3598 {
Jamie Madill437fa652016-05-03 15:13:24 -04003599 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003600 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003601 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003602 }
3603 break;
3604
He Yunchaoced53ae2016-11-29 15:00:51 +08003605 default:
3606 context->handleError(Error(GL_INVALID_ENUM));
3607 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003608 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003609
Jamie Madilla3944d42016-07-22 22:13:26 -04003610 const Format &format = tex->getFormat(textarget, level);
3611 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003612 {
Jamie Madill437fa652016-05-03 15:13:24 -04003613 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003614 return false;
3615 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003616 }
3617
Jamie Madill570f7c82014-07-03 10:38:54 -04003618 return true;
3619}
3620
Geoff Langb1196682014-07-23 13:47:29 -04003621bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003622{
3623 if (program == 0)
3624 {
Jamie Madill437fa652016-05-03 15:13:24 -04003625 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003626 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003627 }
3628
Dian Xiang769769a2015-09-09 15:20:08 -07003629 gl::Program *programObject = GetValidProgram(context, program);
3630 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003631 {
3632 return false;
3633 }
3634
Jamie Madill0063c512014-08-25 15:47:53 -04003635 if (!programObject || !programObject->isLinked())
3636 {
Jamie Madill437fa652016-05-03 15:13:24 -04003637 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003638 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003639 }
3640
Geoff Lang7dd2e102014-11-10 15:19:26 -05003641 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003642 {
Jamie Madill437fa652016-05-03 15:13:24 -04003643 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003644 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003645 }
3646
Jamie Madill0063c512014-08-25 15:47:53 -04003647 return true;
3648}
3649
He Yunchaoced53ae2016-11-29 15:00:51 +08003650bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003651{
3652 return ValidateGetUniformBase(context, program, location);
3653}
3654
He Yunchaoced53ae2016-11-29 15:00:51 +08003655bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003656{
Jamie Madill78f41802014-08-25 15:47:55 -04003657 return ValidateGetUniformBase(context, program, location);
3658}
3659
Geoff Langf41d0ee2016-10-07 13:04:23 -04003660static bool ValidateSizedGetUniform(Context *context,
3661 GLuint program,
3662 GLint location,
3663 GLsizei bufSize,
3664 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003665{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003666 if (length)
3667 {
3668 *length = 0;
3669 }
3670
Jamie Madill78f41802014-08-25 15:47:55 -04003671 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003672 {
Jamie Madill78f41802014-08-25 15:47:55 -04003673 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003674 }
3675
Geoff Langf41d0ee2016-10-07 13:04:23 -04003676 if (bufSize < 0)
3677 {
3678 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3679 return false;
3680 }
3681
Jamie Madilla502c742014-08-28 17:19:13 -04003682 gl::Program *programObject = context->getProgram(program);
3683 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003684
Jamie Madill78f41802014-08-25 15:47:55 -04003685 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003686 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003687 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003688 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003689 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003690 context->handleError(
3691 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003692 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003693 }
3694
Geoff Langf41d0ee2016-10-07 13:04:23 -04003695 if (length)
3696 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003697 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003698 }
3699
Jamie Madill0063c512014-08-25 15:47:53 -04003700 return true;
3701}
3702
He Yunchaoced53ae2016-11-29 15:00:51 +08003703bool ValidateGetnUniformfvEXT(Context *context,
3704 GLuint program,
3705 GLint location,
3706 GLsizei bufSize,
3707 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003708{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003709 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003710}
3711
He Yunchaoced53ae2016-11-29 15:00:51 +08003712bool ValidateGetnUniformivEXT(Context *context,
3713 GLuint program,
3714 GLint location,
3715 GLsizei bufSize,
3716 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003717{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003718 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3719}
3720
3721bool ValidateGetUniformfvRobustANGLE(Context *context,
3722 GLuint program,
3723 GLint location,
3724 GLsizei bufSize,
3725 GLsizei *length,
3726 GLfloat *params)
3727{
3728 if (!ValidateRobustEntryPoint(context, bufSize))
3729 {
3730 return false;
3731 }
3732
3733 // bufSize is validated in ValidateSizedGetUniform
3734 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3735}
3736
3737bool ValidateGetUniformivRobustANGLE(Context *context,
3738 GLuint program,
3739 GLint location,
3740 GLsizei bufSize,
3741 GLsizei *length,
3742 GLint *params)
3743{
3744 if (!ValidateRobustEntryPoint(context, bufSize))
3745 {
3746 return false;
3747 }
3748
3749 // bufSize is validated in ValidateSizedGetUniform
3750 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3751}
3752
3753bool ValidateGetUniformuivRobustANGLE(Context *context,
3754 GLuint program,
3755 GLint location,
3756 GLsizei bufSize,
3757 GLsizei *length,
3758 GLuint *params)
3759{
3760 if (!ValidateRobustEntryPoint(context, bufSize))
3761 {
3762 return false;
3763 }
3764
3765 if (context->getClientMajorVersion() < 3)
3766 {
3767 context->handleError(
3768 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3769 return false;
3770 }
3771
3772 // bufSize is validated in ValidateSizedGetUniform
3773 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003774}
3775
He Yunchaoced53ae2016-11-29 15:00:51 +08003776bool ValidateDiscardFramebufferBase(Context *context,
3777 GLenum target,
3778 GLsizei numAttachments,
3779 const GLenum *attachments,
3780 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003781{
3782 if (numAttachments < 0)
3783 {
Jamie Madill437fa652016-05-03 15:13:24 -04003784 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003785 return false;
3786 }
3787
3788 for (GLsizei i = 0; i < numAttachments; ++i)
3789 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003790 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003791 {
3792 if (defaultFramebuffer)
3793 {
Jamie Madill437fa652016-05-03 15:13:24 -04003794 context->handleError(Error(
3795 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003796 return false;
3797 }
3798
3799 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3800 {
Jamie Madill437fa652016-05-03 15:13:24 -04003801 context->handleError(Error(GL_INVALID_OPERATION,
3802 "Requested color attachment is greater than the maximum "
3803 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003804 return false;
3805 }
3806 }
3807 else
3808 {
3809 switch (attachments[i])
3810 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003811 case GL_DEPTH_ATTACHMENT:
3812 case GL_STENCIL_ATTACHMENT:
3813 case GL_DEPTH_STENCIL_ATTACHMENT:
3814 if (defaultFramebuffer)
3815 {
3816 context->handleError(
3817 Error(GL_INVALID_ENUM,
3818 "Invalid attachment when the default framebuffer is bound"));
3819 return false;
3820 }
3821 break;
3822 case GL_COLOR:
3823 case GL_DEPTH:
3824 case GL_STENCIL:
3825 if (!defaultFramebuffer)
3826 {
3827 context->handleError(
3828 Error(GL_INVALID_ENUM,
3829 "Invalid attachment when the default framebuffer is not bound"));
3830 return false;
3831 }
3832 break;
3833 default:
3834 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003835 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003836 }
3837 }
3838 }
3839
3840 return true;
3841}
3842
Austin Kinross6ee1e782015-05-29 17:05:37 -07003843bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3844{
3845 // Note that debug marker calls must not set error state
3846
3847 if (length < 0)
3848 {
3849 return false;
3850 }
3851
3852 if (marker == nullptr)
3853 {
3854 return false;
3855 }
3856
3857 return true;
3858}
3859
3860bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3861{
3862 // Note that debug marker calls must not set error state
3863
3864 if (length < 0)
3865 {
3866 return false;
3867 }
3868
3869 if (length > 0 && marker == nullptr)
3870 {
3871 return false;
3872 }
3873
3874 return true;
3875}
3876
Geoff Langdcab33b2015-07-21 13:03:16 -04003877bool ValidateEGLImageTargetTexture2DOES(Context *context,
3878 egl::Display *display,
3879 GLenum target,
3880 egl::Image *image)
3881{
Geoff Langa8406172015-07-21 16:53:39 -04003882 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3883 {
Jamie Madill437fa652016-05-03 15:13:24 -04003884 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003885 return false;
3886 }
3887
3888 switch (target)
3889 {
3890 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003891 if (!context->getExtensions().eglImage)
3892 {
3893 context->handleError(Error(
3894 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3895 }
3896 break;
3897
3898 case GL_TEXTURE_EXTERNAL_OES:
3899 if (!context->getExtensions().eglImageExternal)
3900 {
3901 context->handleError(Error(
3902 GL_INVALID_ENUM,
3903 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3904 }
Geoff Langa8406172015-07-21 16:53:39 -04003905 break;
3906
3907 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003908 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003909 return false;
3910 }
3911
3912 if (!display->isValidImage(image))
3913 {
Jamie Madill437fa652016-05-03 15:13:24 -04003914 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003915 return false;
3916 }
3917
3918 if (image->getSamples() > 0)
3919 {
Jamie Madill437fa652016-05-03 15:13:24 -04003920 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003921 "cannot create a 2D texture from a multisampled EGL image."));
3922 return false;
3923 }
3924
Jamie Madilla3944d42016-07-22 22:13:26 -04003925 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003926 if (!textureCaps.texturable)
3927 {
Jamie Madill437fa652016-05-03 15:13:24 -04003928 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003929 "EGL image internal format is not supported as a texture."));
3930 return false;
3931 }
3932
Geoff Langdcab33b2015-07-21 13:03:16 -04003933 return true;
3934}
3935
3936bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3937 egl::Display *display,
3938 GLenum target,
3939 egl::Image *image)
3940{
Geoff Langa8406172015-07-21 16:53:39 -04003941 if (!context->getExtensions().eglImage)
3942 {
Jamie Madill437fa652016-05-03 15:13:24 -04003943 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003944 return false;
3945 }
3946
3947 switch (target)
3948 {
3949 case GL_RENDERBUFFER:
3950 break;
3951
3952 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003953 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003954 return false;
3955 }
3956
3957 if (!display->isValidImage(image))
3958 {
Jamie Madill437fa652016-05-03 15:13:24 -04003959 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003960 return false;
3961 }
3962
Jamie Madilla3944d42016-07-22 22:13:26 -04003963 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003964 if (!textureCaps.renderable)
3965 {
Jamie Madill437fa652016-05-03 15:13:24 -04003966 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003967 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3968 return false;
3969 }
3970
Geoff Langdcab33b2015-07-21 13:03:16 -04003971 return true;
3972}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003973
3974bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3975{
Geoff Lang36167ab2015-12-07 10:27:14 -05003976 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003977 {
3978 // The default VAO should always exist
3979 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003980 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003981 return false;
3982 }
3983
3984 return true;
3985}
3986
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003987bool ValidateLinkProgram(Context *context, GLuint program)
3988{
3989 if (context->hasActiveTransformFeedback(program))
3990 {
3991 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003992 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003993 "Cannot link program while program is associated with an active "
3994 "transform feedback object."));
3995 return false;
3996 }
3997 return true;
3998}
3999
Geoff Langc5629752015-12-07 16:29:04 -05004000bool ValidateProgramBinaryBase(Context *context,
4001 GLuint program,
4002 GLenum binaryFormat,
4003 const void *binary,
4004 GLint length)
4005{
4006 Program *programObject = GetValidProgram(context, program);
4007 if (programObject == nullptr)
4008 {
4009 return false;
4010 }
4011
4012 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4013 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4014 programBinaryFormats.end())
4015 {
Jamie Madill437fa652016-05-03 15:13:24 -04004016 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004017 return false;
4018 }
4019
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004020 if (context->hasActiveTransformFeedback(program))
4021 {
4022 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004023 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004024 "Cannot change program binary while program is associated with "
4025 "an active transform feedback object."));
4026 return false;
4027 }
4028
Geoff Langc5629752015-12-07 16:29:04 -05004029 return true;
4030}
4031
4032bool ValidateGetProgramBinaryBase(Context *context,
4033 GLuint program,
4034 GLsizei bufSize,
4035 GLsizei *length,
4036 GLenum *binaryFormat,
4037 void *binary)
4038{
4039 Program *programObject = GetValidProgram(context, program);
4040 if (programObject == nullptr)
4041 {
4042 return false;
4043 }
4044
4045 if (!programObject->isLinked())
4046 {
Jamie Madill437fa652016-05-03 15:13:24 -04004047 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004048 return false;
4049 }
4050
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004051 if (context->getCaps().programBinaryFormats.empty())
4052 {
4053 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4054 return false;
4055 }
4056
Geoff Langc5629752015-12-07 16:29:04 -05004057 return true;
4058}
Jamie Madillc29968b2016-01-20 11:17:23 -05004059
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004060bool ValidateUseProgram(Context *context, GLuint program)
4061{
4062 if (program != 0)
4063 {
4064 Program *programObject = context->getProgram(program);
4065 if (!programObject)
4066 {
4067 // ES 3.1.0 section 7.3 page 72
4068 if (context->getShader(program))
4069 {
Jamie Madill437fa652016-05-03 15:13:24 -04004070 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004071 Error(GL_INVALID_OPERATION,
4072 "Attempted to use a single shader instead of a shader program."));
4073 return false;
4074 }
4075 else
4076 {
Jamie Madill437fa652016-05-03 15:13:24 -04004077 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004078 return false;
4079 }
4080 }
4081 if (!programObject->isLinked())
4082 {
Jamie Madill437fa652016-05-03 15:13:24 -04004083 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004084 return false;
4085 }
4086 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004087 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004088 {
4089 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004090 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004091 Error(GL_INVALID_OPERATION,
4092 "Cannot change active program while transform feedback is unpaused."));
4093 return false;
4094 }
4095
4096 return true;
4097}
4098
Jamie Madillc29968b2016-01-20 11:17:23 -05004099bool ValidateCopyTexImage2D(ValidationContext *context,
4100 GLenum target,
4101 GLint level,
4102 GLenum internalformat,
4103 GLint x,
4104 GLint y,
4105 GLsizei width,
4106 GLsizei height,
4107 GLint border)
4108{
Martin Radev1be913c2016-07-11 17:59:16 +03004109 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004110 {
4111 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4112 0, x, y, width, height, border);
4113 }
4114
Martin Radev1be913c2016-07-11 17:59:16 +03004115 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004116 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4117 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004118}
Jamie Madillc29968b2016-01-20 11:17:23 -05004119
4120bool ValidateFramebufferRenderbuffer(Context *context,
4121 GLenum target,
4122 GLenum attachment,
4123 GLenum renderbuffertarget,
4124 GLuint renderbuffer)
4125{
4126 if (!ValidFramebufferTarget(target) ||
4127 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4128 {
Jamie Madill437fa652016-05-03 15:13:24 -04004129 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004130 return false;
4131 }
4132
4133 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4134 renderbuffertarget, renderbuffer);
4135}
4136
4137bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4138{
4139 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4140 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4141 {
Jamie Madill437fa652016-05-03 15:13:24 -04004142 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004143 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4144 return false;
4145 }
4146
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004147 ASSERT(context->getGLState().getDrawFramebuffer());
4148 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004149 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4150
4151 // This should come first before the check for the default frame buffer
4152 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4153 // rather than INVALID_OPERATION
4154 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4155 {
4156 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4157
4158 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004159 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4160 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004161 {
4162 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004163 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4164 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4165 // 3.1 is still a bit ambiguous about the error, but future specs are
4166 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004167 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004168 return false;
4169 }
4170 else if (bufs[colorAttachment] >= maxColorAttachment)
4171 {
Jamie Madill437fa652016-05-03 15:13:24 -04004172 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004173 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004174 return false;
4175 }
4176 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4177 frameBufferId != 0)
4178 {
4179 // INVALID_OPERATION-GL is bound to buffer and ith argument
4180 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004181 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004182 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4183 return false;
4184 }
4185 }
4186
4187 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4188 // and n is not 1 or bufs is bound to value other than BACK and NONE
4189 if (frameBufferId == 0)
4190 {
4191 if (n != 1)
4192 {
Jamie Madill437fa652016-05-03 15:13:24 -04004193 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004194 "n must be 1 when GL is bound to the default framebuffer"));
4195 return false;
4196 }
4197
4198 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4199 {
Jamie Madill437fa652016-05-03 15:13:24 -04004200 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004201 GL_INVALID_OPERATION,
4202 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4203 return false;
4204 }
4205 }
4206
4207 return true;
4208}
4209
4210bool ValidateCopyTexSubImage2D(Context *context,
4211 GLenum target,
4212 GLint level,
4213 GLint xoffset,
4214 GLint yoffset,
4215 GLint x,
4216 GLint y,
4217 GLsizei width,
4218 GLsizei height)
4219{
Martin Radev1be913c2016-07-11 17:59:16 +03004220 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004221 {
4222 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4223 yoffset, x, y, width, height, 0);
4224 }
4225
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004226 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4227 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004228}
4229
Geoff Lang496c02d2016-10-20 11:38:11 -07004230bool ValidateGetBufferPointervBase(Context *context,
4231 GLenum target,
4232 GLenum pname,
4233 GLsizei *length,
4234 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004235{
Geoff Lang496c02d2016-10-20 11:38:11 -07004236 if (length)
4237 {
4238 *length = 0;
4239 }
4240
4241 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4242 {
4243 context->handleError(
4244 Error(GL_INVALID_OPERATION,
4245 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
4246 return false;
4247 }
4248
Olli Etuaho4f667482016-03-30 15:56:35 +03004249 if (!ValidBufferTarget(context, target))
4250 {
Jamie Madill437fa652016-05-03 15:13:24 -04004251 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004252 return false;
4253 }
4254
Geoff Lang496c02d2016-10-20 11:38:11 -07004255 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004256 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004257 case GL_BUFFER_MAP_POINTER:
4258 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004259
Geoff Lang496c02d2016-10-20 11:38:11 -07004260 default:
4261 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4262 return false;
4263 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004264
4265 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4266 // target bound to zero generate an INVALID_OPERATION error."
4267 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004268 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004269 {
Jamie Madill437fa652016-05-03 15:13:24 -04004270 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004271 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4272 return false;
4273 }
4274
Geoff Lang496c02d2016-10-20 11:38:11 -07004275 if (length)
4276 {
4277 *length = 1;
4278 }
4279
Olli Etuaho4f667482016-03-30 15:56:35 +03004280 return true;
4281}
4282
4283bool ValidateUnmapBufferBase(Context *context, GLenum target)
4284{
4285 if (!ValidBufferTarget(context, target))
4286 {
Jamie Madill437fa652016-05-03 15:13:24 -04004287 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004288 return false;
4289 }
4290
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004291 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004292
4293 if (buffer == nullptr || !buffer->isMapped())
4294 {
Jamie Madill437fa652016-05-03 15:13:24 -04004295 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004296 return false;
4297 }
4298
4299 return true;
4300}
4301
4302bool ValidateMapBufferRangeBase(Context *context,
4303 GLenum target,
4304 GLintptr offset,
4305 GLsizeiptr length,
4306 GLbitfield access)
4307{
4308 if (!ValidBufferTarget(context, target))
4309 {
Jamie Madill437fa652016-05-03 15:13:24 -04004310 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004311 return false;
4312 }
4313
4314 if (offset < 0 || length < 0)
4315 {
Jamie Madill437fa652016-05-03 15:13:24 -04004316 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004317 return false;
4318 }
4319
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004320 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004321
4322 if (!buffer)
4323 {
Jamie Madill437fa652016-05-03 15:13:24 -04004324 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004325 return false;
4326 }
4327
4328 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004329 CheckedNumeric<size_t> checkedOffset(offset);
4330 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004331
Jamie Madille2e406c2016-06-02 13:04:10 -04004332 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004333 {
Jamie Madill437fa652016-05-03 15:13:24 -04004334 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004335 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4336 return false;
4337 }
4338
4339 // Check for invalid bits in the mask
4340 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4341 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4342 GL_MAP_UNSYNCHRONIZED_BIT;
4343
4344 if (access & ~(allAccessBits))
4345 {
Jamie Madill437fa652016-05-03 15:13:24 -04004346 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004347 return false;
4348 }
4349
4350 if (length == 0)
4351 {
Jamie Madill437fa652016-05-03 15:13:24 -04004352 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004353 return false;
4354 }
4355
4356 if (buffer->isMapped())
4357 {
Jamie Madill437fa652016-05-03 15:13:24 -04004358 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004359 return false;
4360 }
4361
4362 // Check for invalid bit combinations
4363 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4364 {
Jamie Madill437fa652016-05-03 15:13:24 -04004365 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004366 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4367 return false;
4368 }
4369
4370 GLbitfield writeOnlyBits =
4371 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4372
4373 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4374 {
Jamie Madill437fa652016-05-03 15:13:24 -04004375 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004376 "Invalid access bits when mapping buffer for reading: 0x%X.",
4377 access));
4378 return false;
4379 }
4380
4381 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4382 {
Jamie Madill437fa652016-05-03 15:13:24 -04004383 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004384 GL_INVALID_OPERATION,
4385 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4386 return false;
4387 }
4388 return true;
4389}
4390
4391bool ValidateFlushMappedBufferRangeBase(Context *context,
4392 GLenum target,
4393 GLintptr offset,
4394 GLsizeiptr length)
4395{
4396 if (offset < 0 || length < 0)
4397 {
Jamie Madill437fa652016-05-03 15:13:24 -04004398 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004399 return false;
4400 }
4401
4402 if (!ValidBufferTarget(context, target))
4403 {
Jamie Madill437fa652016-05-03 15:13:24 -04004404 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004405 return false;
4406 }
4407
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004408 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004409
4410 if (buffer == nullptr)
4411 {
Jamie Madill437fa652016-05-03 15:13:24 -04004412 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004413 return false;
4414 }
4415
4416 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4417 {
Jamie Madill437fa652016-05-03 15:13:24 -04004418 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004419 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4420 return false;
4421 }
4422
4423 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004424 CheckedNumeric<size_t> checkedOffset(offset);
4425 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004426
Jamie Madille2e406c2016-06-02 13:04:10 -04004427 if (!checkedSize.IsValid() ||
4428 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004429 {
Jamie Madill437fa652016-05-03 15:13:24 -04004430 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004431 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4432 return false;
4433 }
4434
4435 return true;
4436}
4437
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004438bool ValidateGenerateMipmap(Context *context, GLenum target)
4439{
4440 if (!ValidTextureTarget(context, target))
4441 {
4442 context->handleError(Error(GL_INVALID_ENUM));
4443 return false;
4444 }
4445
4446 Texture *texture = context->getTargetTexture(target);
4447
4448 if (texture == nullptr)
4449 {
4450 context->handleError(Error(GL_INVALID_OPERATION));
4451 return false;
4452 }
4453
4454 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4455
4456 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4457 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4458 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4459 {
4460 context->handleError(Error(GL_INVALID_OPERATION));
4461 return false;
4462 }
4463
Jamie Madilla3944d42016-07-22 22:13:26 -04004464 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4465 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4466 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004467
4468 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4469 // unsized formats or that are color renderable and filterable. Since we do not track if
4470 // the texture was created with sized or unsized format (only sized formats are stored),
4471 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4472 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4473 // textures since they're the only texture format that can be created with unsized formats
4474 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4475 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004476 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4477 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004478 {
4479 context->handleError(Error(GL_INVALID_OPERATION));
4480 return false;
4481 }
4482
4483 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004484 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004485 {
4486 context->handleError(Error(GL_INVALID_OPERATION));
4487 return false;
4488 }
4489
4490 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004491 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004492 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4493 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4494 {
Geoff Lang55482a12016-11-21 16:54:01 -05004495 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004496 context->handleError(Error(GL_INVALID_OPERATION));
4497 return false;
4498 }
4499
4500 // Cube completeness check
4501 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4502 {
4503 context->handleError(Error(GL_INVALID_OPERATION));
4504 return false;
4505 }
4506
4507 return true;
4508}
4509
Olli Etuaho41997e72016-03-10 13:38:39 +02004510bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4511{
4512 return ValidateGenOrDelete(context, n);
4513}
4514
4515bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4516{
4517 return ValidateGenOrDelete(context, n);
4518}
4519
4520bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4521{
4522 return ValidateGenOrDelete(context, n);
4523}
4524
4525bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4526{
4527 return ValidateGenOrDelete(context, n);
4528}
4529
4530bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4531{
4532 return ValidateGenOrDelete(context, n);
4533}
4534
4535bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4536{
4537 return ValidateGenOrDelete(context, n);
4538}
4539
4540bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4541{
4542 return ValidateGenOrDelete(context, n);
4543}
4544
4545bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4546{
4547 return ValidateGenOrDelete(context, n);
4548}
4549
4550bool ValidateGenOrDelete(Context *context, GLint n)
4551{
4552 if (n < 0)
4553 {
Jamie Madill437fa652016-05-03 15:13:24 -04004554 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004555 return false;
4556 }
4557 return true;
4558}
4559
Geoff Langf41a7152016-09-19 15:11:17 -04004560bool ValidateEnable(Context *context, GLenum cap)
4561{
4562 if (!ValidCap(context, cap, false))
4563 {
4564 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4565 return false;
4566 }
4567
4568 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4569 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4570 {
4571 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4572 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4573
4574 // We also output an error message to the debugger window if tracing is active, so that
4575 // developers can see the error message.
4576 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004577 return false;
4578 }
4579
4580 return true;
4581}
4582
4583bool ValidateDisable(Context *context, GLenum cap)
4584{
4585 if (!ValidCap(context, cap, false))
4586 {
4587 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4588 return false;
4589 }
4590
4591 return true;
4592}
4593
4594bool ValidateIsEnabled(Context *context, GLenum cap)
4595{
4596 if (!ValidCap(context, cap, true))
4597 {
4598 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4599 return false;
4600 }
4601
4602 return true;
4603}
4604
Geoff Langff5b2d52016-09-07 11:32:23 -04004605bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4606{
4607 if (!context->getExtensions().robustClientMemory)
4608 {
4609 context->handleError(
4610 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4611 return false;
4612 }
4613
4614 if (bufSize < 0)
4615 {
4616 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4617 return false;
4618 }
4619
4620 return true;
4621}
4622
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004623bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4624{
4625 if (bufSize < numParams)
4626 {
4627 context->handleError(Error(GL_INVALID_OPERATION,
4628 "%u parameters are required but %i were provided.", numParams,
4629 bufSize));
4630 return false;
4631 }
4632
4633 return true;
4634}
4635
Geoff Langff5b2d52016-09-07 11:32:23 -04004636bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4637 GLenum target,
4638 GLenum attachment,
4639 GLenum pname,
4640 GLsizei *numParams)
4641{
4642 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4643 *numParams = 1;
4644
4645 if (!ValidFramebufferTarget(target))
4646 {
4647 context->handleError(Error(GL_INVALID_ENUM));
4648 return false;
4649 }
4650
4651 int clientVersion = context->getClientMajorVersion();
4652
4653 switch (pname)
4654 {
4655 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4656 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4657 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4658 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4659 break;
4660
4661 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4662 if (clientVersion < 3 && !context->getExtensions().sRGB)
4663 {
4664 context->handleError(Error(GL_INVALID_ENUM));
4665 return false;
4666 }
4667 break;
4668
4669 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4670 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4671 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4672 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4673 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4674 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4675 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4676 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4677 if (clientVersion < 3)
4678 {
4679 context->handleError(Error(GL_INVALID_ENUM));
4680 return false;
4681 }
4682 break;
4683
4684 default:
4685 context->handleError(Error(GL_INVALID_ENUM));
4686 return false;
4687 }
4688
4689 // Determine if the attachment is a valid enum
4690 switch (attachment)
4691 {
4692 case GL_BACK:
4693 case GL_FRONT:
4694 case GL_DEPTH:
4695 case GL_STENCIL:
4696 case GL_DEPTH_STENCIL_ATTACHMENT:
4697 if (clientVersion < 3)
4698 {
4699 context->handleError(Error(GL_INVALID_ENUM));
4700 return false;
4701 }
4702 break;
4703
4704 case GL_DEPTH_ATTACHMENT:
4705 case GL_STENCIL_ATTACHMENT:
4706 break;
4707
4708 default:
4709 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4710 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4711 {
4712 context->handleError(Error(GL_INVALID_ENUM));
4713 return false;
4714 }
4715 break;
4716 }
4717
4718 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4719 ASSERT(framebuffer);
4720
4721 if (framebuffer->id() == 0)
4722 {
4723 if (clientVersion < 3)
4724 {
4725 context->handleError(Error(GL_INVALID_OPERATION));
4726 return false;
4727 }
4728
4729 switch (attachment)
4730 {
4731 case GL_BACK:
4732 case GL_DEPTH:
4733 case GL_STENCIL:
4734 break;
4735
4736 default:
4737 context->handleError(Error(GL_INVALID_OPERATION));
4738 return false;
4739 }
4740 }
4741 else
4742 {
4743 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4744 {
4745 // Valid attachment query
4746 }
4747 else
4748 {
4749 switch (attachment)
4750 {
4751 case GL_DEPTH_ATTACHMENT:
4752 case GL_STENCIL_ATTACHMENT:
4753 break;
4754
4755 case GL_DEPTH_STENCIL_ATTACHMENT:
4756 if (!framebuffer->hasValidDepthStencil())
4757 {
4758 context->handleError(Error(GL_INVALID_OPERATION));
4759 return false;
4760 }
4761 break;
4762
4763 default:
4764 context->handleError(Error(GL_INVALID_OPERATION));
4765 return false;
4766 }
4767 }
4768 }
4769
4770 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4771 if (attachmentObject)
4772 {
4773 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4774 attachmentObject->type() == GL_TEXTURE ||
4775 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4776
4777 switch (pname)
4778 {
4779 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4780 if (attachmentObject->type() != GL_RENDERBUFFER &&
4781 attachmentObject->type() != GL_TEXTURE)
4782 {
4783 context->handleError(Error(GL_INVALID_ENUM));
4784 return false;
4785 }
4786 break;
4787
4788 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4789 if (attachmentObject->type() != GL_TEXTURE)
4790 {
4791 context->handleError(Error(GL_INVALID_ENUM));
4792 return false;
4793 }
4794 break;
4795
4796 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4797 if (attachmentObject->type() != GL_TEXTURE)
4798 {
4799 context->handleError(Error(GL_INVALID_ENUM));
4800 return false;
4801 }
4802 break;
4803
4804 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4805 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4806 {
4807 context->handleError(Error(GL_INVALID_OPERATION));
4808 return false;
4809 }
4810 break;
4811
4812 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4813 if (attachmentObject->type() != GL_TEXTURE)
4814 {
4815 context->handleError(Error(GL_INVALID_ENUM));
4816 return false;
4817 }
4818 break;
4819
4820 default:
4821 break;
4822 }
4823 }
4824 else
4825 {
4826 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4827 // is NONE, then querying any other pname will generate INVALID_ENUM.
4828
4829 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4830 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4831 // INVALID_OPERATION for all other pnames
4832
4833 switch (pname)
4834 {
4835 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4836 break;
4837
4838 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4839 if (clientVersion < 3)
4840 {
4841 context->handleError(Error(GL_INVALID_ENUM));
4842 return false;
4843 }
4844 break;
4845
4846 default:
4847 if (clientVersion < 3)
4848 {
4849 context->handleError(Error(GL_INVALID_ENUM));
4850 return false;
4851 }
4852 else
4853 {
4854 context->handleError(Error(GL_INVALID_OPERATION));
4855 return false;
4856 }
4857 }
4858 }
4859
4860 return true;
4861}
4862
4863bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4864 GLenum target,
4865 GLenum attachment,
4866 GLenum pname,
4867 GLsizei bufSize,
4868 GLsizei *numParams)
4869{
4870 if (!ValidateRobustEntryPoint(context, bufSize))
4871 {
4872 return false;
4873 }
4874
4875 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4876 {
4877 return false;
4878 }
4879
4880 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4881 {
4882 return false;
4883 }
4884
4885 return true;
4886}
4887
4888bool ValidateGetBufferParameteriv(ValidationContext *context,
4889 GLenum target,
4890 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004891 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004892{
Geoff Langebebe1c2016-10-14 12:01:31 -04004893 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004894}
4895
4896bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4897 GLenum target,
4898 GLenum pname,
4899 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004900 GLsizei *length,
4901 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004902{
4903 if (!ValidateRobustEntryPoint(context, bufSize))
4904 {
4905 return false;
4906 }
4907
Geoff Langebebe1c2016-10-14 12:01:31 -04004908 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004909 {
4910 return false;
4911 }
4912
Geoff Langebebe1c2016-10-14 12:01:31 -04004913 if (!ValidateRobustBufferSize(context, bufSize, *length))
4914 {
4915 return false;
4916 }
4917
4918 return true;
4919}
4920
4921bool ValidateGetBufferParameteri64v(ValidationContext *context,
4922 GLenum target,
4923 GLenum pname,
4924 GLint64 *params)
4925{
4926 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4927}
4928
4929bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4930 GLenum target,
4931 GLenum pname,
4932 GLsizei bufSize,
4933 GLsizei *length,
4934 GLint64 *params)
4935{
4936 if (!ValidateRobustEntryPoint(context, bufSize))
4937 {
4938 return false;
4939 }
4940
4941 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4942 {
4943 return false;
4944 }
4945
4946 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004947 {
4948 return false;
4949 }
4950
4951 return true;
4952}
4953
4954bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4955{
4956 // Currently, all GetProgramiv queries return 1 parameter
4957 *numParams = 1;
4958
4959 Program *programObject = GetValidProgram(context, program);
4960 if (!programObject)
4961 {
4962 return false;
4963 }
4964
4965 switch (pname)
4966 {
4967 case GL_DELETE_STATUS:
4968 case GL_LINK_STATUS:
4969 case GL_VALIDATE_STATUS:
4970 case GL_INFO_LOG_LENGTH:
4971 case GL_ATTACHED_SHADERS:
4972 case GL_ACTIVE_ATTRIBUTES:
4973 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4974 case GL_ACTIVE_UNIFORMS:
4975 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4976 break;
4977
4978 case GL_PROGRAM_BINARY_LENGTH:
4979 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4980 {
4981 context->handleError(Error(GL_INVALID_ENUM,
4982 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4983 "GL_OES_get_program_binary or ES 3.0."));
4984 return false;
4985 }
4986 break;
4987
4988 case GL_ACTIVE_UNIFORM_BLOCKS:
4989 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4990 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4991 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4992 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4993 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4994 if (context->getClientMajorVersion() < 3)
4995 {
4996 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4997 return false;
4998 }
4999 break;
5000
5001 default:
5002 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5003 return false;
5004 }
5005
5006 return true;
5007}
5008
5009bool ValidateGetProgramivRobustANGLE(Context *context,
5010 GLuint program,
5011 GLenum pname,
5012 GLsizei bufSize,
5013 GLsizei *numParams)
5014{
5015 if (!ValidateRobustEntryPoint(context, bufSize))
5016 {
5017 return false;
5018 }
5019
5020 if (!ValidateGetProgramiv(context, program, pname, numParams))
5021 {
5022 return false;
5023 }
5024
5025 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5026 {
5027 return false;
5028 }
5029
5030 return true;
5031}
5032
Geoff Lang740d9022016-10-07 11:20:52 -04005033bool ValidateGetRenderbufferParameteriv(Context *context,
5034 GLenum target,
5035 GLenum pname,
5036 GLint *params)
5037{
5038 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5039}
5040
5041bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5042 GLenum target,
5043 GLenum pname,
5044 GLsizei bufSize,
5045 GLsizei *length,
5046 GLint *params)
5047{
5048 if (!ValidateRobustEntryPoint(context, bufSize))
5049 {
5050 return false;
5051 }
5052
5053 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5054 {
5055 return false;
5056 }
5057
5058 if (!ValidateRobustBufferSize(context, bufSize, *length))
5059 {
5060 return false;
5061 }
5062
5063 return true;
5064}
5065
Geoff Langd7d0ed32016-10-07 11:33:51 -04005066bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5067{
5068 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5069}
5070
5071bool ValidateGetShaderivRobustANGLE(Context *context,
5072 GLuint shader,
5073 GLenum pname,
5074 GLsizei bufSize,
5075 GLsizei *length,
5076 GLint *params)
5077{
5078 if (!ValidateRobustEntryPoint(context, bufSize))
5079 {
5080 return false;
5081 }
5082
5083 if (!ValidateGetShaderivBase(context, shader, pname, length))
5084 {
5085 return false;
5086 }
5087
5088 if (!ValidateRobustBufferSize(context, bufSize, *length))
5089 {
5090 return false;
5091 }
5092
5093 return true;
5094}
5095
Geoff Langc1984ed2016-10-07 12:41:00 -04005096bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5097{
5098 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5099}
5100
5101bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5102 GLenum target,
5103 GLenum pname,
5104 GLsizei bufSize,
5105 GLsizei *length,
5106 GLfloat *params)
5107{
5108 if (!ValidateRobustEntryPoint(context, bufSize))
5109 {
5110 return false;
5111 }
5112
5113 if (!ValidateGetTexParameterBase(context, target, pname, length))
5114 {
5115 return false;
5116 }
5117
5118 if (!ValidateRobustBufferSize(context, bufSize, *length))
5119 {
5120 return false;
5121 }
5122
5123 return true;
5124}
5125
5126bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5127{
5128 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5129}
5130
5131bool ValidateGetTexParameterivRobustANGLE(Context *context,
5132 GLenum target,
5133 GLenum pname,
5134 GLsizei bufSize,
5135 GLsizei *length,
5136 GLint *params)
5137{
5138 if (!ValidateRobustEntryPoint(context, bufSize))
5139 {
5140 return false;
5141 }
5142
5143 if (!ValidateGetTexParameterBase(context, target, pname, length))
5144 {
5145 return false;
5146 }
5147
5148 if (!ValidateRobustBufferSize(context, bufSize, *length))
5149 {
5150 return false;
5151 }
5152
5153 return true;
5154}
5155
5156bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5157{
5158 return ValidateTexParameterBase(context, target, pname, -1, &param);
5159}
5160
5161bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5162{
5163 return ValidateTexParameterBase(context, target, pname, -1, params);
5164}
5165
5166bool ValidateTexParameterfvRobustANGLE(Context *context,
5167 GLenum target,
5168 GLenum pname,
5169 GLsizei bufSize,
5170 const GLfloat *params)
5171{
5172 if (!ValidateRobustEntryPoint(context, bufSize))
5173 {
5174 return false;
5175 }
5176
5177 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5178}
5179
5180bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5181{
5182 return ValidateTexParameterBase(context, target, pname, -1, &param);
5183}
5184
5185bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5186{
5187 return ValidateTexParameterBase(context, target, pname, -1, params);
5188}
5189
5190bool ValidateTexParameterivRobustANGLE(Context *context,
5191 GLenum target,
5192 GLenum pname,
5193 GLsizei bufSize,
5194 const GLint *params)
5195{
5196 if (!ValidateRobustEntryPoint(context, bufSize))
5197 {
5198 return false;
5199 }
5200
5201 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5202}
5203
5204bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5205{
5206 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5207}
5208
5209bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5210 GLuint sampler,
5211 GLenum pname,
5212 GLuint bufSize,
5213 GLsizei *length,
5214 GLfloat *params)
5215{
5216 if (!ValidateRobustEntryPoint(context, bufSize))
5217 {
5218 return false;
5219 }
5220
5221 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5222 {
5223 return false;
5224 }
5225
5226 if (!ValidateRobustBufferSize(context, bufSize, *length))
5227 {
5228 return false;
5229 }
5230
5231 return true;
5232}
5233
5234bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5235{
5236 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5237}
5238
5239bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5240 GLuint sampler,
5241 GLenum pname,
5242 GLuint bufSize,
5243 GLsizei *length,
5244 GLint *params)
5245{
5246 if (!ValidateRobustEntryPoint(context, bufSize))
5247 {
5248 return false;
5249 }
5250
5251 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5252 {
5253 return false;
5254 }
5255
5256 if (!ValidateRobustBufferSize(context, bufSize, *length))
5257 {
5258 return false;
5259 }
5260
5261 return true;
5262}
5263
5264bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5265{
5266 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5267}
5268
5269bool ValidateSamplerParameterfv(Context *context,
5270 GLuint sampler,
5271 GLenum pname,
5272 const GLfloat *params)
5273{
5274 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5275}
5276
5277bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5278 GLuint sampler,
5279 GLenum pname,
5280 GLsizei bufSize,
5281 const GLfloat *params)
5282{
5283 if (!ValidateRobustEntryPoint(context, bufSize))
5284 {
5285 return false;
5286 }
5287
5288 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5289}
5290
5291bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5292{
5293 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5294}
5295
5296bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5297{
5298 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5299}
5300
5301bool ValidateSamplerParameterivRobustANGLE(Context *context,
5302 GLuint sampler,
5303 GLenum pname,
5304 GLsizei bufSize,
5305 const GLint *params)
5306{
5307 if (!ValidateRobustEntryPoint(context, bufSize))
5308 {
5309 return false;
5310 }
5311
5312 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5313}
5314
Geoff Lang0b031062016-10-13 14:30:04 -04005315bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5316{
5317 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5318}
5319
5320bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5321 GLuint index,
5322 GLenum pname,
5323 GLsizei bufSize,
5324 GLsizei *length,
5325 GLfloat *params)
5326{
5327 if (!ValidateRobustEntryPoint(context, bufSize))
5328 {
5329 return false;
5330 }
5331
5332 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5333 {
5334 return false;
5335 }
5336
5337 if (!ValidateRobustBufferSize(context, bufSize, *length))
5338 {
5339 return false;
5340 }
5341
5342 return true;
5343}
5344
5345bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5346{
5347 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5348}
5349
5350bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5351 GLuint index,
5352 GLenum pname,
5353 GLsizei bufSize,
5354 GLsizei *length,
5355 GLint *params)
5356{
5357 if (!ValidateRobustEntryPoint(context, bufSize))
5358 {
5359 return false;
5360 }
5361
5362 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5363 {
5364 return false;
5365 }
5366
5367 if (!ValidateRobustBufferSize(context, bufSize, *length))
5368 {
5369 return false;
5370 }
5371
5372 return true;
5373}
5374
5375bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5376{
5377 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5378}
5379
5380bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5381 GLuint index,
5382 GLenum pname,
5383 GLsizei bufSize,
5384 GLsizei *length,
5385 void **pointer)
5386{
5387 if (!ValidateRobustEntryPoint(context, bufSize))
5388 {
5389 return false;
5390 }
5391
5392 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5393 {
5394 return false;
5395 }
5396
5397 if (!ValidateRobustBufferSize(context, bufSize, *length))
5398 {
5399 return false;
5400 }
5401
5402 return true;
5403}
5404
5405bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5406{
5407 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5408}
5409
5410bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5411 GLuint index,
5412 GLenum pname,
5413 GLsizei bufSize,
5414 GLsizei *length,
5415 GLint *params)
5416{
5417 if (!ValidateRobustEntryPoint(context, bufSize))
5418 {
5419 return false;
5420 }
5421
5422 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5423 {
5424 return false;
5425 }
5426
5427 if (!ValidateRobustBufferSize(context, bufSize, *length))
5428 {
5429 return false;
5430 }
5431
5432 return true;
5433}
5434
5435bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5436{
5437 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5438}
5439
5440bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5441 GLuint index,
5442 GLenum pname,
5443 GLsizei bufSize,
5444 GLsizei *length,
5445 GLuint *params)
5446{
5447 if (!ValidateRobustEntryPoint(context, bufSize))
5448 {
5449 return false;
5450 }
5451
5452 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5453 {
5454 return false;
5455 }
5456
5457 if (!ValidateRobustBufferSize(context, bufSize, *length))
5458 {
5459 return false;
5460 }
5461
5462 return true;
5463}
5464
Geoff Lang6899b872016-10-14 11:30:13 -04005465bool ValidateGetActiveUniformBlockiv(Context *context,
5466 GLuint program,
5467 GLuint uniformBlockIndex,
5468 GLenum pname,
5469 GLint *params)
5470{
5471 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5472}
5473
5474bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5475 GLuint program,
5476 GLuint uniformBlockIndex,
5477 GLenum pname,
5478 GLsizei bufSize,
5479 GLsizei *length,
5480 GLint *params)
5481{
5482 if (!ValidateRobustEntryPoint(context, bufSize))
5483 {
5484 return false;
5485 }
5486
5487 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5488 {
5489 return false;
5490 }
5491
5492 if (!ValidateRobustBufferSize(context, bufSize, *length))
5493 {
5494 return false;
5495 }
5496
5497 return true;
5498}
5499
Geoff Lang0a9661f2016-10-20 10:59:20 -07005500bool ValidateGetInternalFormativ(Context *context,
5501 GLenum target,
5502 GLenum internalformat,
5503 GLenum pname,
5504 GLsizei bufSize,
5505 GLint *params)
5506{
5507 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5508 nullptr);
5509}
5510
5511bool ValidateGetInternalFormativRobustANGLE(Context *context,
5512 GLenum target,
5513 GLenum internalformat,
5514 GLenum pname,
5515 GLsizei bufSize,
5516 GLsizei *length,
5517 GLint *params)
5518{
5519 if (!ValidateRobustEntryPoint(context, bufSize))
5520 {
5521 return false;
5522 }
5523
5524 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5525 {
5526 return false;
5527 }
5528
5529 if (!ValidateRobustBufferSize(context, bufSize, *length))
5530 {
5531 return false;
5532 }
5533
5534 return true;
5535}
5536
Jamie Madillc29968b2016-01-20 11:17:23 -05005537} // namespace gl