blob: 9483931636cbd0ab39b2d3ff3644c10f3bab5d68 [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();
Geoff Lang3a86ad32015-09-01 11:47:05 -04003117 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04003118 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04003119 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
He Yunchaoced53ae2016-11-29 15:00:51 +08003120 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
3121 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003122 const DepthStencilState &depthStencilState = state.getDepthStencilState();
3123 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3124 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04003125 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04003126 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3127 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04003128 {
3129 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3130 // Section 6.10 of the WebGL 1.0 spec
He Yunchaoced53ae2016-11-29 15:00:51 +08003131 ERR("This ANGLE implementation does not support separate front/back stencil "
Geoff Lang3a86ad32015-09-01 11:47:05 -04003132 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04003133 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003134 return false;
3135 }
Jamie Madillac528012014-06-20 13:21:23 -04003136 }
3137
Jamie Madill51f40ec2016-06-15 14:06:00 -04003138 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003139 {
Jamie Madill437fa652016-05-03 15:13:24 -04003140 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003141 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003142 }
3143
Geoff Lang7dd2e102014-11-10 15:19:26 -05003144 gl::Program *program = state.getProgram();
3145 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003146 {
Jamie Madill437fa652016-05-03 15:13:24 -04003147 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003148 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003149 }
3150
Geoff Lang7dd2e102014-11-10 15:19:26 -05003151 if (!program->validateSamplers(NULL, context->getCaps()))
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
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003157 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003158 for (unsigned int uniformBlockIndex = 0;
3159 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003160 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003161 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003162 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003163 const OffsetBindingPointer<Buffer> &uniformBuffer =
3164 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003165
Geoff Lang5d124a62015-09-15 13:03:27 -04003166 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003167 {
3168 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003169 context->handleError(
3170 Error(GL_INVALID_OPERATION,
3171 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003172 return false;
3173 }
3174
Geoff Lang5d124a62015-09-15 13:03:27 -04003175 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003176 if (uniformBufferSize == 0)
3177 {
3178 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003179 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003180 }
3181
Jamie Madill62d31cb2015-09-11 13:25:51 -04003182 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003183 {
3184 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003185 context->handleError(
3186 Error(GL_INVALID_OPERATION,
3187 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003188 return false;
3189 }
3190 }
3191
Jamie Madill250d33f2014-06-06 17:09:03 -04003192 // No-op if zero count
3193 return (count > 0);
3194}
3195
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003196bool ValidateDrawArrays(ValidationContext *context,
3197 GLenum mode,
3198 GLint first,
3199 GLsizei count,
3200 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003201{
Jamie Madillfd716582014-06-06 17:09:04 -04003202 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003203 {
Jamie Madill437fa652016-05-03 15:13:24 -04003204 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003205 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003206 }
3207
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003208 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003209 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003210 if (curTransformFeedback && curTransformFeedback->isActive() &&
3211 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003212 {
3213 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003214 // that does not match the current transform feedback object's draw mode (if transform
3215 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003216 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003217 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003218 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003219 }
3220
Jiajia Qind9671222016-11-29 16:30:31 +08003221 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003222 {
3223 return false;
3224 }
3225
Corentin Wallez71168a02016-12-19 15:11:18 -08003226 // Check the computation of maxVertex doesn't overflow.
3227 // - first < 0 or count < 0 have been checked as an error condition
3228 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3229 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3230 ASSERT(count > 0 && first >= 0);
3231 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3232 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003233 {
3234 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3235 return false;
3236 }
3237
Corentin Wallez71168a02016-12-19 15:11:18 -08003238 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003239 {
3240 return false;
3241 }
3242
3243 return true;
3244}
3245
He Yunchaoced53ae2016-11-29 15:00:51 +08003246bool ValidateDrawArraysInstanced(Context *context,
3247 GLenum mode,
3248 GLint first,
3249 GLsizei count,
3250 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003251{
3252 if (primcount < 0)
3253 {
Jamie Madill437fa652016-05-03 15:13:24 -04003254 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003255 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003256 }
3257
Jamie Madill2b976812014-08-25 15:47:49 -04003258 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003259 {
3260 return false;
3261 }
3262
3263 // No-op if zero primitive count
3264 return (primcount > 0);
3265}
3266
Geoff Lang87a93302014-09-16 13:29:43 -04003267static bool ValidateDrawInstancedANGLE(Context *context)
3268{
3269 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003270 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003271
Geoff Lang7dd2e102014-11-10 15:19:26 -05003272 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003273
3274 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003275 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003276 {
3277 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003278 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003279 {
3280 return true;
3281 }
3282 }
3283
Jamie Madill437fa652016-05-03 15:13:24 -04003284 context->handleError(Error(GL_INVALID_OPERATION,
3285 "ANGLE_instanced_arrays requires that at least one active attribute"
3286 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003287 return false;
3288}
3289
He Yunchaoced53ae2016-11-29 15:00:51 +08003290bool ValidateDrawArraysInstancedANGLE(Context *context,
3291 GLenum mode,
3292 GLint first,
3293 GLsizei count,
3294 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003295{
3296 if (!ValidateDrawInstancedANGLE(context))
3297 {
3298 return false;
3299 }
3300
3301 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3302}
3303
Jiajia Qind9671222016-11-29 16:30:31 +08003304bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003305{
Jamie Madill250d33f2014-06-06 17:09:03 -04003306 switch (type)
3307 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003308 case GL_UNSIGNED_BYTE:
3309 case GL_UNSIGNED_SHORT:
3310 break;
3311 case GL_UNSIGNED_INT:
3312 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3313 {
3314 context->handleError(Error(GL_INVALID_ENUM));
3315 return false;
3316 }
3317 break;
3318 default:
3319 context->handleError(Error(GL_INVALID_ENUM));
3320 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003321 }
3322
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003323 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003324
3325 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003326 if (curTransformFeedback && curTransformFeedback->isActive() &&
3327 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003328 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003329 // It is an invalid operation to call DrawElements, DrawRangeElements or
3330 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003331 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003332 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003333 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003334 }
3335
Jiajia Qind9671222016-11-29 16:30:31 +08003336 return true;
3337}
3338
3339bool ValidateDrawElements(ValidationContext *context,
3340 GLenum mode,
3341 GLsizei count,
3342 GLenum type,
3343 const GLvoid *indices,
3344 GLsizei primcount,
3345 IndexRange *indexRangeOut)
3346{
3347 if (!ValidateDrawElementsBase(context, type))
3348 return false;
3349
3350 const State &state = context->getGLState();
3351
Jamie Madill250d33f2014-06-06 17:09:03 -04003352 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003353 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003354 {
Jamie Madill437fa652016-05-03 15:13:24 -04003355 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003356 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003357 }
3358
He Yunchaoced53ae2016-11-29 15:00:51 +08003359 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003360 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003361
Jamie Madillae3000b2014-08-25 15:47:51 -04003362 if (elementArrayBuffer)
3363 {
3364 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3365
3366 GLint64 offset = reinterpret_cast<GLint64>(indices);
He Yunchaoced53ae2016-11-29 15:00:51 +08003367 GLint64 byteCount =
3368 static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count) + offset;
Jamie Madillae3000b2014-08-25 15:47:51 -04003369
3370 // check for integer overflows
3371 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3372 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3373 {
Jamie Madill437fa652016-05-03 15:13:24 -04003374 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003375 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003376 }
3377
3378 // Check for reading past the end of the bound buffer object
3379 if (byteCount > elementArrayBuffer->getSize())
3380 {
Jamie Madill437fa652016-05-03 15:13:24 -04003381 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003382 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003383 }
3384 }
Corentin Wallez327411e2016-12-09 11:09:17 -05003385 else if (context->getExtensions().webglCompatibility && count > 0)
3386 {
3387 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3388 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3389 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3390 context->handleError(
3391 Error(GL_INVALID_OPERATION, "There is no element array buffer bound and count > 0."));
3392 return false;
3393 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003394 else if (!indices)
3395 {
Corentin Wallez327411e2016-12-09 11:09:17 -05003396 // This is an application error that would normally result in a crash,
3397 // but we catch it and return an error
3398 context->handleError(
3399 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003400 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003401 }
3402
Jiajia Qind9671222016-11-29 16:30:31 +08003403 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003404 {
3405 return false;
3406 }
3407
Jamie Madill2b976812014-08-25 15:47:49 -04003408 // Use max index to validate if our vertex buffers are large enough for the pull.
3409 // TODO: offer fast path, with disabled index validation.
3410 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3411 if (elementArrayBuffer)
3412 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003413 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003414 Error error =
3415 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3416 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003417 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003418 {
Jamie Madill437fa652016-05-03 15:13:24 -04003419 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003420 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003421 }
3422 }
3423 else
3424 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003425 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003426 }
3427
Jamie Madille79b1e12015-11-04 16:36:37 -05003428 // If we use an index greater than our maximum supported index range, return an error.
3429 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3430 // return an error if possible here.
3431 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3432 {
Jamie Madill437fa652016-05-03 15:13:24 -04003433 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003434 return false;
3435 }
3436
Corentin Wallez92db6942016-12-09 13:10:36 -05003437 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3438 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003439 {
3440 return false;
3441 }
3442
Geoff Lang3edfe032015-09-04 16:38:24 -04003443 // No op if there are no real indices in the index data (all are primitive restart).
3444 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003445}
3446
Geoff Langb1196682014-07-23 13:47:29 -04003447bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003448 GLenum mode,
3449 GLsizei count,
3450 GLenum type,
3451 const GLvoid *indices,
3452 GLsizei primcount,
3453 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003454{
3455 if (primcount < 0)
3456 {
Jamie Madill437fa652016-05-03 15:13:24 -04003457 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003458 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003459 }
3460
Jamie Madill2b976812014-08-25 15:47:49 -04003461 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003462 {
3463 return false;
3464 }
3465
3466 // No-op zero primitive count
3467 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003468}
3469
Geoff Lang3edfe032015-09-04 16:38:24 -04003470bool ValidateDrawElementsInstancedANGLE(Context *context,
3471 GLenum mode,
3472 GLsizei count,
3473 GLenum type,
3474 const GLvoid *indices,
3475 GLsizei primcount,
3476 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003477{
3478 if (!ValidateDrawInstancedANGLE(context))
3479 {
3480 return false;
3481 }
3482
He Yunchaoced53ae2016-11-29 15:00:51 +08003483 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3484 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003485}
3486
He Yunchaoced53ae2016-11-29 15:00:51 +08003487bool ValidateFramebufferTextureBase(Context *context,
3488 GLenum target,
3489 GLenum attachment,
3490 GLuint texture,
3491 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003492{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003493 if (!ValidFramebufferTarget(target))
3494 {
Jamie Madill437fa652016-05-03 15:13:24 -04003495 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003496 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003497 }
3498
3499 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003500 {
3501 return false;
3502 }
3503
Jamie Madill55ec3b12014-07-03 10:38:57 -04003504 if (texture != 0)
3505 {
3506 gl::Texture *tex = context->getTexture(texture);
3507
3508 if (tex == NULL)
3509 {
Jamie Madill437fa652016-05-03 15:13:24 -04003510 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003511 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003512 }
3513
3514 if (level < 0)
3515 {
Jamie Madill437fa652016-05-03 15:13:24 -04003516 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003517 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003518 }
3519 }
3520
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003521 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003522 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003523
Jamie Madill84115c92015-04-23 15:00:07 -04003524 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003525 {
Jamie Madill437fa652016-05-03 15:13:24 -04003526 context->handleError(
3527 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003528 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003529 }
3530
3531 return true;
3532}
3533
He Yunchaoced53ae2016-11-29 15:00:51 +08003534bool ValidateFramebufferTexture2D(Context *context,
3535 GLenum target,
3536 GLenum attachment,
3537 GLenum textarget,
3538 GLuint texture,
3539 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003540{
He Yunchaoced53ae2016-11-29 15:00:51 +08003541 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3542 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003543 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3544 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003545 {
Jamie Madill437fa652016-05-03 15:13:24 -04003546 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003547 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003548 }
3549
3550 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003551 {
3552 return false;
3553 }
3554
Jamie Madill55ec3b12014-07-03 10:38:57 -04003555 if (texture != 0)
3556 {
3557 gl::Texture *tex = context->getTexture(texture);
3558 ASSERT(tex);
3559
Jamie Madill2a6564e2014-07-11 09:53:19 -04003560 const gl::Caps &caps = context->getCaps();
3561
Jamie Madill55ec3b12014-07-03 10:38:57 -04003562 switch (textarget)
3563 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003564 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003565 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003566 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003567 {
Jamie Madill437fa652016-05-03 15:13:24 -04003568 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003569 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003570 }
3571 if (tex->getTarget() != GL_TEXTURE_2D)
3572 {
Jamie Madill437fa652016-05-03 15:13:24 -04003573 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003574 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003575 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003576 }
3577 break;
3578
He Yunchaoced53ae2016-11-29 15:00:51 +08003579 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3580 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3581 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3582 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3583 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3584 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003585 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003586 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003587 {
Jamie Madill437fa652016-05-03 15:13:24 -04003588 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003589 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003590 }
3591 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3592 {
Jamie Madill437fa652016-05-03 15:13:24 -04003593 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003594 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003595 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003596 }
3597 break;
3598
He Yunchaoced53ae2016-11-29 15:00:51 +08003599 default:
3600 context->handleError(Error(GL_INVALID_ENUM));
3601 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003602 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003603
Jamie Madilla3944d42016-07-22 22:13:26 -04003604 const Format &format = tex->getFormat(textarget, level);
3605 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003606 {
Jamie Madill437fa652016-05-03 15:13:24 -04003607 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003608 return false;
3609 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003610 }
3611
Jamie Madill570f7c82014-07-03 10:38:54 -04003612 return true;
3613}
3614
Geoff Langb1196682014-07-23 13:47:29 -04003615bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003616{
3617 if (program == 0)
3618 {
Jamie Madill437fa652016-05-03 15:13:24 -04003619 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003620 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003621 }
3622
Dian Xiang769769a2015-09-09 15:20:08 -07003623 gl::Program *programObject = GetValidProgram(context, program);
3624 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003625 {
3626 return false;
3627 }
3628
Jamie Madill0063c512014-08-25 15:47:53 -04003629 if (!programObject || !programObject->isLinked())
3630 {
Jamie Madill437fa652016-05-03 15:13:24 -04003631 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003632 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003633 }
3634
Geoff Lang7dd2e102014-11-10 15:19:26 -05003635 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003636 {
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 Madill549c7fd2014-08-25 15:47:56 -04003639 }
3640
Jamie Madill0063c512014-08-25 15:47:53 -04003641 return true;
3642}
3643
He Yunchaoced53ae2016-11-29 15:00:51 +08003644bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003645{
3646 return ValidateGetUniformBase(context, program, location);
3647}
3648
He Yunchaoced53ae2016-11-29 15:00:51 +08003649bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003650{
Jamie Madill78f41802014-08-25 15:47:55 -04003651 return ValidateGetUniformBase(context, program, location);
3652}
3653
Geoff Langf41d0ee2016-10-07 13:04:23 -04003654static bool ValidateSizedGetUniform(Context *context,
3655 GLuint program,
3656 GLint location,
3657 GLsizei bufSize,
3658 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003659{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003660 if (length)
3661 {
3662 *length = 0;
3663 }
3664
Jamie Madill78f41802014-08-25 15:47:55 -04003665 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003666 {
Jamie Madill78f41802014-08-25 15:47:55 -04003667 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003668 }
3669
Geoff Langf41d0ee2016-10-07 13:04:23 -04003670 if (bufSize < 0)
3671 {
3672 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3673 return false;
3674 }
3675
Jamie Madilla502c742014-08-28 17:19:13 -04003676 gl::Program *programObject = context->getProgram(program);
3677 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003678
Jamie Madill78f41802014-08-25 15:47:55 -04003679 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003680 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003681 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003682 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003683 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003684 context->handleError(
3685 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003686 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003687 }
3688
Geoff Langf41d0ee2016-10-07 13:04:23 -04003689 if (length)
3690 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003691 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003692 }
3693
Jamie Madill0063c512014-08-25 15:47:53 -04003694 return true;
3695}
3696
He Yunchaoced53ae2016-11-29 15:00:51 +08003697bool ValidateGetnUniformfvEXT(Context *context,
3698 GLuint program,
3699 GLint location,
3700 GLsizei bufSize,
3701 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003702{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003703 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003704}
3705
He Yunchaoced53ae2016-11-29 15:00:51 +08003706bool ValidateGetnUniformivEXT(Context *context,
3707 GLuint program,
3708 GLint location,
3709 GLsizei bufSize,
3710 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003711{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003712 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3713}
3714
3715bool ValidateGetUniformfvRobustANGLE(Context *context,
3716 GLuint program,
3717 GLint location,
3718 GLsizei bufSize,
3719 GLsizei *length,
3720 GLfloat *params)
3721{
3722 if (!ValidateRobustEntryPoint(context, bufSize))
3723 {
3724 return false;
3725 }
3726
3727 // bufSize is validated in ValidateSizedGetUniform
3728 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3729}
3730
3731bool ValidateGetUniformivRobustANGLE(Context *context,
3732 GLuint program,
3733 GLint location,
3734 GLsizei bufSize,
3735 GLsizei *length,
3736 GLint *params)
3737{
3738 if (!ValidateRobustEntryPoint(context, bufSize))
3739 {
3740 return false;
3741 }
3742
3743 // bufSize is validated in ValidateSizedGetUniform
3744 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3745}
3746
3747bool ValidateGetUniformuivRobustANGLE(Context *context,
3748 GLuint program,
3749 GLint location,
3750 GLsizei bufSize,
3751 GLsizei *length,
3752 GLuint *params)
3753{
3754 if (!ValidateRobustEntryPoint(context, bufSize))
3755 {
3756 return false;
3757 }
3758
3759 if (context->getClientMajorVersion() < 3)
3760 {
3761 context->handleError(
3762 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3763 return false;
3764 }
3765
3766 // bufSize is validated in ValidateSizedGetUniform
3767 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003768}
3769
He Yunchaoced53ae2016-11-29 15:00:51 +08003770bool ValidateDiscardFramebufferBase(Context *context,
3771 GLenum target,
3772 GLsizei numAttachments,
3773 const GLenum *attachments,
3774 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003775{
3776 if (numAttachments < 0)
3777 {
Jamie Madill437fa652016-05-03 15:13:24 -04003778 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003779 return false;
3780 }
3781
3782 for (GLsizei i = 0; i < numAttachments; ++i)
3783 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003784 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003785 {
3786 if (defaultFramebuffer)
3787 {
Jamie Madill437fa652016-05-03 15:13:24 -04003788 context->handleError(Error(
3789 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003790 return false;
3791 }
3792
3793 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3794 {
Jamie Madill437fa652016-05-03 15:13:24 -04003795 context->handleError(Error(GL_INVALID_OPERATION,
3796 "Requested color attachment is greater than the maximum "
3797 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003798 return false;
3799 }
3800 }
3801 else
3802 {
3803 switch (attachments[i])
3804 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003805 case GL_DEPTH_ATTACHMENT:
3806 case GL_STENCIL_ATTACHMENT:
3807 case GL_DEPTH_STENCIL_ATTACHMENT:
3808 if (defaultFramebuffer)
3809 {
3810 context->handleError(
3811 Error(GL_INVALID_ENUM,
3812 "Invalid attachment when the default framebuffer is bound"));
3813 return false;
3814 }
3815 break;
3816 case GL_COLOR:
3817 case GL_DEPTH:
3818 case GL_STENCIL:
3819 if (!defaultFramebuffer)
3820 {
3821 context->handleError(
3822 Error(GL_INVALID_ENUM,
3823 "Invalid attachment when the default framebuffer is not bound"));
3824 return false;
3825 }
3826 break;
3827 default:
3828 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003829 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003830 }
3831 }
3832 }
3833
3834 return true;
3835}
3836
Austin Kinross6ee1e782015-05-29 17:05:37 -07003837bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3838{
3839 // Note that debug marker calls must not set error state
3840
3841 if (length < 0)
3842 {
3843 return false;
3844 }
3845
3846 if (marker == nullptr)
3847 {
3848 return false;
3849 }
3850
3851 return true;
3852}
3853
3854bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3855{
3856 // Note that debug marker calls must not set error state
3857
3858 if (length < 0)
3859 {
3860 return false;
3861 }
3862
3863 if (length > 0 && marker == nullptr)
3864 {
3865 return false;
3866 }
3867
3868 return true;
3869}
3870
Geoff Langdcab33b2015-07-21 13:03:16 -04003871bool ValidateEGLImageTargetTexture2DOES(Context *context,
3872 egl::Display *display,
3873 GLenum target,
3874 egl::Image *image)
3875{
Geoff Langa8406172015-07-21 16:53:39 -04003876 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3877 {
Jamie Madill437fa652016-05-03 15:13:24 -04003878 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003879 return false;
3880 }
3881
3882 switch (target)
3883 {
3884 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003885 if (!context->getExtensions().eglImage)
3886 {
3887 context->handleError(Error(
3888 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3889 }
3890 break;
3891
3892 case GL_TEXTURE_EXTERNAL_OES:
3893 if (!context->getExtensions().eglImageExternal)
3894 {
3895 context->handleError(Error(
3896 GL_INVALID_ENUM,
3897 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3898 }
Geoff Langa8406172015-07-21 16:53:39 -04003899 break;
3900
3901 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003902 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003903 return false;
3904 }
3905
3906 if (!display->isValidImage(image))
3907 {
Jamie Madill437fa652016-05-03 15:13:24 -04003908 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003909 return false;
3910 }
3911
3912 if (image->getSamples() > 0)
3913 {
Jamie Madill437fa652016-05-03 15:13:24 -04003914 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003915 "cannot create a 2D texture from a multisampled EGL image."));
3916 return false;
3917 }
3918
Jamie Madilla3944d42016-07-22 22:13:26 -04003919 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003920 if (!textureCaps.texturable)
3921 {
Jamie Madill437fa652016-05-03 15:13:24 -04003922 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003923 "EGL image internal format is not supported as a texture."));
3924 return false;
3925 }
3926
Geoff Langdcab33b2015-07-21 13:03:16 -04003927 return true;
3928}
3929
3930bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3931 egl::Display *display,
3932 GLenum target,
3933 egl::Image *image)
3934{
Geoff Langa8406172015-07-21 16:53:39 -04003935 if (!context->getExtensions().eglImage)
3936 {
Jamie Madill437fa652016-05-03 15:13:24 -04003937 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003938 return false;
3939 }
3940
3941 switch (target)
3942 {
3943 case GL_RENDERBUFFER:
3944 break;
3945
3946 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003947 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003948 return false;
3949 }
3950
3951 if (!display->isValidImage(image))
3952 {
Jamie Madill437fa652016-05-03 15:13:24 -04003953 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003954 return false;
3955 }
3956
Jamie Madilla3944d42016-07-22 22:13:26 -04003957 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003958 if (!textureCaps.renderable)
3959 {
Jamie Madill437fa652016-05-03 15:13:24 -04003960 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003961 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3962 return false;
3963 }
3964
Geoff Langdcab33b2015-07-21 13:03:16 -04003965 return true;
3966}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003967
3968bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3969{
Geoff Lang36167ab2015-12-07 10:27:14 -05003970 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003971 {
3972 // The default VAO should always exist
3973 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003974 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003975 return false;
3976 }
3977
3978 return true;
3979}
3980
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003981bool ValidateLinkProgram(Context *context, GLuint program)
3982{
3983 if (context->hasActiveTransformFeedback(program))
3984 {
3985 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003986 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003987 "Cannot link program while program is associated with an active "
3988 "transform feedback object."));
3989 return false;
3990 }
3991 return true;
3992}
3993
Geoff Langc5629752015-12-07 16:29:04 -05003994bool ValidateProgramBinaryBase(Context *context,
3995 GLuint program,
3996 GLenum binaryFormat,
3997 const void *binary,
3998 GLint length)
3999{
4000 Program *programObject = GetValidProgram(context, program);
4001 if (programObject == nullptr)
4002 {
4003 return false;
4004 }
4005
4006 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4007 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4008 programBinaryFormats.end())
4009 {
Jamie Madill437fa652016-05-03 15:13:24 -04004010 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004011 return false;
4012 }
4013
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004014 if (context->hasActiveTransformFeedback(program))
4015 {
4016 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004017 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004018 "Cannot change program binary while program is associated with "
4019 "an active transform feedback object."));
4020 return false;
4021 }
4022
Geoff Langc5629752015-12-07 16:29:04 -05004023 return true;
4024}
4025
4026bool ValidateGetProgramBinaryBase(Context *context,
4027 GLuint program,
4028 GLsizei bufSize,
4029 GLsizei *length,
4030 GLenum *binaryFormat,
4031 void *binary)
4032{
4033 Program *programObject = GetValidProgram(context, program);
4034 if (programObject == nullptr)
4035 {
4036 return false;
4037 }
4038
4039 if (!programObject->isLinked())
4040 {
Jamie Madill437fa652016-05-03 15:13:24 -04004041 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004042 return false;
4043 }
4044
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004045 if (context->getCaps().programBinaryFormats.empty())
4046 {
4047 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4048 return false;
4049 }
4050
Geoff Langc5629752015-12-07 16:29:04 -05004051 return true;
4052}
Jamie Madillc29968b2016-01-20 11:17:23 -05004053
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004054bool ValidateUseProgram(Context *context, GLuint program)
4055{
4056 if (program != 0)
4057 {
4058 Program *programObject = context->getProgram(program);
4059 if (!programObject)
4060 {
4061 // ES 3.1.0 section 7.3 page 72
4062 if (context->getShader(program))
4063 {
Jamie Madill437fa652016-05-03 15:13:24 -04004064 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004065 Error(GL_INVALID_OPERATION,
4066 "Attempted to use a single shader instead of a shader program."));
4067 return false;
4068 }
4069 else
4070 {
Jamie Madill437fa652016-05-03 15:13:24 -04004071 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004072 return false;
4073 }
4074 }
4075 if (!programObject->isLinked())
4076 {
Jamie Madill437fa652016-05-03 15:13:24 -04004077 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004078 return false;
4079 }
4080 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004081 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004082 {
4083 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004084 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004085 Error(GL_INVALID_OPERATION,
4086 "Cannot change active program while transform feedback is unpaused."));
4087 return false;
4088 }
4089
4090 return true;
4091}
4092
Jamie Madillc29968b2016-01-20 11:17:23 -05004093bool ValidateCopyTexImage2D(ValidationContext *context,
4094 GLenum target,
4095 GLint level,
4096 GLenum internalformat,
4097 GLint x,
4098 GLint y,
4099 GLsizei width,
4100 GLsizei height,
4101 GLint border)
4102{
Martin Radev1be913c2016-07-11 17:59:16 +03004103 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004104 {
4105 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4106 0, x, y, width, height, border);
4107 }
4108
Martin Radev1be913c2016-07-11 17:59:16 +03004109 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004110 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4111 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004112}
Jamie Madillc29968b2016-01-20 11:17:23 -05004113
4114bool ValidateFramebufferRenderbuffer(Context *context,
4115 GLenum target,
4116 GLenum attachment,
4117 GLenum renderbuffertarget,
4118 GLuint renderbuffer)
4119{
4120 if (!ValidFramebufferTarget(target) ||
4121 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4122 {
Jamie Madill437fa652016-05-03 15:13:24 -04004123 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004124 return false;
4125 }
4126
4127 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4128 renderbuffertarget, renderbuffer);
4129}
4130
4131bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4132{
4133 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4134 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4135 {
Jamie Madill437fa652016-05-03 15:13:24 -04004136 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004137 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4138 return false;
4139 }
4140
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004141 ASSERT(context->getGLState().getDrawFramebuffer());
4142 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004143 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4144
4145 // This should come first before the check for the default frame buffer
4146 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4147 // rather than INVALID_OPERATION
4148 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4149 {
4150 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4151
4152 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004153 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4154 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004155 {
4156 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004157 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4158 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4159 // 3.1 is still a bit ambiguous about the error, but future specs are
4160 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004161 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004162 return false;
4163 }
4164 else if (bufs[colorAttachment] >= maxColorAttachment)
4165 {
Jamie Madill437fa652016-05-03 15:13:24 -04004166 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004167 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004168 return false;
4169 }
4170 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4171 frameBufferId != 0)
4172 {
4173 // INVALID_OPERATION-GL is bound to buffer and ith argument
4174 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004175 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004176 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4177 return false;
4178 }
4179 }
4180
4181 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4182 // and n is not 1 or bufs is bound to value other than BACK and NONE
4183 if (frameBufferId == 0)
4184 {
4185 if (n != 1)
4186 {
Jamie Madill437fa652016-05-03 15:13:24 -04004187 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004188 "n must be 1 when GL is bound to the default framebuffer"));
4189 return false;
4190 }
4191
4192 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4193 {
Jamie Madill437fa652016-05-03 15:13:24 -04004194 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004195 GL_INVALID_OPERATION,
4196 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4197 return false;
4198 }
4199 }
4200
4201 return true;
4202}
4203
4204bool ValidateCopyTexSubImage2D(Context *context,
4205 GLenum target,
4206 GLint level,
4207 GLint xoffset,
4208 GLint yoffset,
4209 GLint x,
4210 GLint y,
4211 GLsizei width,
4212 GLsizei height)
4213{
Martin Radev1be913c2016-07-11 17:59:16 +03004214 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004215 {
4216 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4217 yoffset, x, y, width, height, 0);
4218 }
4219
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004220 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4221 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004222}
4223
Geoff Lang496c02d2016-10-20 11:38:11 -07004224bool ValidateGetBufferPointervBase(Context *context,
4225 GLenum target,
4226 GLenum pname,
4227 GLsizei *length,
4228 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004229{
Geoff Lang496c02d2016-10-20 11:38:11 -07004230 if (length)
4231 {
4232 *length = 0;
4233 }
4234
4235 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4236 {
4237 context->handleError(
4238 Error(GL_INVALID_OPERATION,
4239 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
4240 return false;
4241 }
4242
Olli Etuaho4f667482016-03-30 15:56:35 +03004243 if (!ValidBufferTarget(context, target))
4244 {
Jamie Madill437fa652016-05-03 15:13:24 -04004245 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004246 return false;
4247 }
4248
Geoff Lang496c02d2016-10-20 11:38:11 -07004249 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004250 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004251 case GL_BUFFER_MAP_POINTER:
4252 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004253
Geoff Lang496c02d2016-10-20 11:38:11 -07004254 default:
4255 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4256 return false;
4257 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004258
4259 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4260 // target bound to zero generate an INVALID_OPERATION error."
4261 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004262 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004263 {
Jamie Madill437fa652016-05-03 15:13:24 -04004264 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004265 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4266 return false;
4267 }
4268
Geoff Lang496c02d2016-10-20 11:38:11 -07004269 if (length)
4270 {
4271 *length = 1;
4272 }
4273
Olli Etuaho4f667482016-03-30 15:56:35 +03004274 return true;
4275}
4276
4277bool ValidateUnmapBufferBase(Context *context, GLenum target)
4278{
4279 if (!ValidBufferTarget(context, target))
4280 {
Jamie Madill437fa652016-05-03 15:13:24 -04004281 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004282 return false;
4283 }
4284
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004285 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004286
4287 if (buffer == nullptr || !buffer->isMapped())
4288 {
Jamie Madill437fa652016-05-03 15:13:24 -04004289 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004290 return false;
4291 }
4292
4293 return true;
4294}
4295
4296bool ValidateMapBufferRangeBase(Context *context,
4297 GLenum target,
4298 GLintptr offset,
4299 GLsizeiptr length,
4300 GLbitfield access)
4301{
4302 if (!ValidBufferTarget(context, target))
4303 {
Jamie Madill437fa652016-05-03 15:13:24 -04004304 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004305 return false;
4306 }
4307
4308 if (offset < 0 || length < 0)
4309 {
Jamie Madill437fa652016-05-03 15:13:24 -04004310 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004311 return false;
4312 }
4313
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004314 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004315
4316 if (!buffer)
4317 {
Jamie Madill437fa652016-05-03 15:13:24 -04004318 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004319 return false;
4320 }
4321
4322 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004323 CheckedNumeric<size_t> checkedOffset(offset);
4324 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004325
Jamie Madille2e406c2016-06-02 13:04:10 -04004326 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004327 {
Jamie Madill437fa652016-05-03 15:13:24 -04004328 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004329 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4330 return false;
4331 }
4332
4333 // Check for invalid bits in the mask
4334 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4335 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4336 GL_MAP_UNSYNCHRONIZED_BIT;
4337
4338 if (access & ~(allAccessBits))
4339 {
Jamie Madill437fa652016-05-03 15:13:24 -04004340 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004341 return false;
4342 }
4343
4344 if (length == 0)
4345 {
Jamie Madill437fa652016-05-03 15:13:24 -04004346 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004347 return false;
4348 }
4349
4350 if (buffer->isMapped())
4351 {
Jamie Madill437fa652016-05-03 15:13:24 -04004352 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004353 return false;
4354 }
4355
4356 // Check for invalid bit combinations
4357 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4358 {
Jamie Madill437fa652016-05-03 15:13:24 -04004359 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004360 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4361 return false;
4362 }
4363
4364 GLbitfield writeOnlyBits =
4365 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4366
4367 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4368 {
Jamie Madill437fa652016-05-03 15:13:24 -04004369 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004370 "Invalid access bits when mapping buffer for reading: 0x%X.",
4371 access));
4372 return false;
4373 }
4374
4375 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4376 {
Jamie Madill437fa652016-05-03 15:13:24 -04004377 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004378 GL_INVALID_OPERATION,
4379 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4380 return false;
4381 }
4382 return true;
4383}
4384
4385bool ValidateFlushMappedBufferRangeBase(Context *context,
4386 GLenum target,
4387 GLintptr offset,
4388 GLsizeiptr length)
4389{
4390 if (offset < 0 || length < 0)
4391 {
Jamie Madill437fa652016-05-03 15:13:24 -04004392 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004393 return false;
4394 }
4395
4396 if (!ValidBufferTarget(context, target))
4397 {
Jamie Madill437fa652016-05-03 15:13:24 -04004398 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004399 return false;
4400 }
4401
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004402 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004403
4404 if (buffer == nullptr)
4405 {
Jamie Madill437fa652016-05-03 15:13:24 -04004406 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004407 return false;
4408 }
4409
4410 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4411 {
Jamie Madill437fa652016-05-03 15:13:24 -04004412 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004413 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4414 return false;
4415 }
4416
4417 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004418 CheckedNumeric<size_t> checkedOffset(offset);
4419 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004420
Jamie Madille2e406c2016-06-02 13:04:10 -04004421 if (!checkedSize.IsValid() ||
4422 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004423 {
Jamie Madill437fa652016-05-03 15:13:24 -04004424 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004425 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4426 return false;
4427 }
4428
4429 return true;
4430}
4431
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004432bool ValidateGenerateMipmap(Context *context, GLenum target)
4433{
4434 if (!ValidTextureTarget(context, target))
4435 {
4436 context->handleError(Error(GL_INVALID_ENUM));
4437 return false;
4438 }
4439
4440 Texture *texture = context->getTargetTexture(target);
4441
4442 if (texture == nullptr)
4443 {
4444 context->handleError(Error(GL_INVALID_OPERATION));
4445 return false;
4446 }
4447
4448 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4449
4450 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4451 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4452 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4453 {
4454 context->handleError(Error(GL_INVALID_OPERATION));
4455 return false;
4456 }
4457
Jamie Madilla3944d42016-07-22 22:13:26 -04004458 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4459 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4460 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004461
4462 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4463 // unsized formats or that are color renderable and filterable. Since we do not track if
4464 // the texture was created with sized or unsized format (only sized formats are stored),
4465 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4466 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4467 // textures since they're the only texture format that can be created with unsized formats
4468 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4469 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004470 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4471 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004472 {
4473 context->handleError(Error(GL_INVALID_OPERATION));
4474 return false;
4475 }
4476
4477 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004478 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004479 {
4480 context->handleError(Error(GL_INVALID_OPERATION));
4481 return false;
4482 }
4483
4484 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004485 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004486 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4487 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4488 {
Geoff Lang55482a12016-11-21 16:54:01 -05004489 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004490 context->handleError(Error(GL_INVALID_OPERATION));
4491 return false;
4492 }
4493
4494 // Cube completeness check
4495 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4496 {
4497 context->handleError(Error(GL_INVALID_OPERATION));
4498 return false;
4499 }
4500
4501 return true;
4502}
4503
Olli Etuaho41997e72016-03-10 13:38:39 +02004504bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4505{
4506 return ValidateGenOrDelete(context, n);
4507}
4508
4509bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4510{
4511 return ValidateGenOrDelete(context, n);
4512}
4513
4514bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4515{
4516 return ValidateGenOrDelete(context, n);
4517}
4518
4519bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4520{
4521 return ValidateGenOrDelete(context, n);
4522}
4523
4524bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4525{
4526 return ValidateGenOrDelete(context, n);
4527}
4528
4529bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4530{
4531 return ValidateGenOrDelete(context, n);
4532}
4533
4534bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4535{
4536 return ValidateGenOrDelete(context, n);
4537}
4538
4539bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4540{
4541 return ValidateGenOrDelete(context, n);
4542}
4543
4544bool ValidateGenOrDelete(Context *context, GLint n)
4545{
4546 if (n < 0)
4547 {
Jamie Madill437fa652016-05-03 15:13:24 -04004548 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004549 return false;
4550 }
4551 return true;
4552}
4553
Geoff Langf41a7152016-09-19 15:11:17 -04004554bool ValidateEnable(Context *context, GLenum cap)
4555{
4556 if (!ValidCap(context, cap, false))
4557 {
4558 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4559 return false;
4560 }
4561
4562 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4563 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4564 {
4565 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4566 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4567
4568 // We also output an error message to the debugger window if tracing is active, so that
4569 // developers can see the error message.
4570 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004571 return false;
4572 }
4573
4574 return true;
4575}
4576
4577bool ValidateDisable(Context *context, GLenum cap)
4578{
4579 if (!ValidCap(context, cap, false))
4580 {
4581 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4582 return false;
4583 }
4584
4585 return true;
4586}
4587
4588bool ValidateIsEnabled(Context *context, GLenum cap)
4589{
4590 if (!ValidCap(context, cap, true))
4591 {
4592 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4593 return false;
4594 }
4595
4596 return true;
4597}
4598
Geoff Langff5b2d52016-09-07 11:32:23 -04004599bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4600{
4601 if (!context->getExtensions().robustClientMemory)
4602 {
4603 context->handleError(
4604 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4605 return false;
4606 }
4607
4608 if (bufSize < 0)
4609 {
4610 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4611 return false;
4612 }
4613
4614 return true;
4615}
4616
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004617bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4618{
4619 if (bufSize < numParams)
4620 {
4621 context->handleError(Error(GL_INVALID_OPERATION,
4622 "%u parameters are required but %i were provided.", numParams,
4623 bufSize));
4624 return false;
4625 }
4626
4627 return true;
4628}
4629
Geoff Langff5b2d52016-09-07 11:32:23 -04004630bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4631 GLenum target,
4632 GLenum attachment,
4633 GLenum pname,
4634 GLsizei *numParams)
4635{
4636 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4637 *numParams = 1;
4638
4639 if (!ValidFramebufferTarget(target))
4640 {
4641 context->handleError(Error(GL_INVALID_ENUM));
4642 return false;
4643 }
4644
4645 int clientVersion = context->getClientMajorVersion();
4646
4647 switch (pname)
4648 {
4649 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4650 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4651 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4652 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4653 break;
4654
4655 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4656 if (clientVersion < 3 && !context->getExtensions().sRGB)
4657 {
4658 context->handleError(Error(GL_INVALID_ENUM));
4659 return false;
4660 }
4661 break;
4662
4663 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4664 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4665 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4666 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4667 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4668 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4669 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4670 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4671 if (clientVersion < 3)
4672 {
4673 context->handleError(Error(GL_INVALID_ENUM));
4674 return false;
4675 }
4676 break;
4677
4678 default:
4679 context->handleError(Error(GL_INVALID_ENUM));
4680 return false;
4681 }
4682
4683 // Determine if the attachment is a valid enum
4684 switch (attachment)
4685 {
4686 case GL_BACK:
4687 case GL_FRONT:
4688 case GL_DEPTH:
4689 case GL_STENCIL:
4690 case GL_DEPTH_STENCIL_ATTACHMENT:
4691 if (clientVersion < 3)
4692 {
4693 context->handleError(Error(GL_INVALID_ENUM));
4694 return false;
4695 }
4696 break;
4697
4698 case GL_DEPTH_ATTACHMENT:
4699 case GL_STENCIL_ATTACHMENT:
4700 break;
4701
4702 default:
4703 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4704 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4705 {
4706 context->handleError(Error(GL_INVALID_ENUM));
4707 return false;
4708 }
4709 break;
4710 }
4711
4712 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4713 ASSERT(framebuffer);
4714
4715 if (framebuffer->id() == 0)
4716 {
4717 if (clientVersion < 3)
4718 {
4719 context->handleError(Error(GL_INVALID_OPERATION));
4720 return false;
4721 }
4722
4723 switch (attachment)
4724 {
4725 case GL_BACK:
4726 case GL_DEPTH:
4727 case GL_STENCIL:
4728 break;
4729
4730 default:
4731 context->handleError(Error(GL_INVALID_OPERATION));
4732 return false;
4733 }
4734 }
4735 else
4736 {
4737 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4738 {
4739 // Valid attachment query
4740 }
4741 else
4742 {
4743 switch (attachment)
4744 {
4745 case GL_DEPTH_ATTACHMENT:
4746 case GL_STENCIL_ATTACHMENT:
4747 break;
4748
4749 case GL_DEPTH_STENCIL_ATTACHMENT:
4750 if (!framebuffer->hasValidDepthStencil())
4751 {
4752 context->handleError(Error(GL_INVALID_OPERATION));
4753 return false;
4754 }
4755 break;
4756
4757 default:
4758 context->handleError(Error(GL_INVALID_OPERATION));
4759 return false;
4760 }
4761 }
4762 }
4763
4764 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4765 if (attachmentObject)
4766 {
4767 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4768 attachmentObject->type() == GL_TEXTURE ||
4769 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4770
4771 switch (pname)
4772 {
4773 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4774 if (attachmentObject->type() != GL_RENDERBUFFER &&
4775 attachmentObject->type() != GL_TEXTURE)
4776 {
4777 context->handleError(Error(GL_INVALID_ENUM));
4778 return false;
4779 }
4780 break;
4781
4782 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4783 if (attachmentObject->type() != GL_TEXTURE)
4784 {
4785 context->handleError(Error(GL_INVALID_ENUM));
4786 return false;
4787 }
4788 break;
4789
4790 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4791 if (attachmentObject->type() != GL_TEXTURE)
4792 {
4793 context->handleError(Error(GL_INVALID_ENUM));
4794 return false;
4795 }
4796 break;
4797
4798 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4799 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4800 {
4801 context->handleError(Error(GL_INVALID_OPERATION));
4802 return false;
4803 }
4804 break;
4805
4806 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4807 if (attachmentObject->type() != GL_TEXTURE)
4808 {
4809 context->handleError(Error(GL_INVALID_ENUM));
4810 return false;
4811 }
4812 break;
4813
4814 default:
4815 break;
4816 }
4817 }
4818 else
4819 {
4820 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4821 // is NONE, then querying any other pname will generate INVALID_ENUM.
4822
4823 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4824 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4825 // INVALID_OPERATION for all other pnames
4826
4827 switch (pname)
4828 {
4829 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4830 break;
4831
4832 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4833 if (clientVersion < 3)
4834 {
4835 context->handleError(Error(GL_INVALID_ENUM));
4836 return false;
4837 }
4838 break;
4839
4840 default:
4841 if (clientVersion < 3)
4842 {
4843 context->handleError(Error(GL_INVALID_ENUM));
4844 return false;
4845 }
4846 else
4847 {
4848 context->handleError(Error(GL_INVALID_OPERATION));
4849 return false;
4850 }
4851 }
4852 }
4853
4854 return true;
4855}
4856
4857bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4858 GLenum target,
4859 GLenum attachment,
4860 GLenum pname,
4861 GLsizei bufSize,
4862 GLsizei *numParams)
4863{
4864 if (!ValidateRobustEntryPoint(context, bufSize))
4865 {
4866 return false;
4867 }
4868
4869 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4870 {
4871 return false;
4872 }
4873
4874 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4875 {
4876 return false;
4877 }
4878
4879 return true;
4880}
4881
4882bool ValidateGetBufferParameteriv(ValidationContext *context,
4883 GLenum target,
4884 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004885 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004886{
Geoff Langebebe1c2016-10-14 12:01:31 -04004887 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004888}
4889
4890bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4891 GLenum target,
4892 GLenum pname,
4893 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004894 GLsizei *length,
4895 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004896{
4897 if (!ValidateRobustEntryPoint(context, bufSize))
4898 {
4899 return false;
4900 }
4901
Geoff Langebebe1c2016-10-14 12:01:31 -04004902 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004903 {
4904 return false;
4905 }
4906
Geoff Langebebe1c2016-10-14 12:01:31 -04004907 if (!ValidateRobustBufferSize(context, bufSize, *length))
4908 {
4909 return false;
4910 }
4911
4912 return true;
4913}
4914
4915bool ValidateGetBufferParameteri64v(ValidationContext *context,
4916 GLenum target,
4917 GLenum pname,
4918 GLint64 *params)
4919{
4920 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4921}
4922
4923bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4924 GLenum target,
4925 GLenum pname,
4926 GLsizei bufSize,
4927 GLsizei *length,
4928 GLint64 *params)
4929{
4930 if (!ValidateRobustEntryPoint(context, bufSize))
4931 {
4932 return false;
4933 }
4934
4935 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4936 {
4937 return false;
4938 }
4939
4940 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004941 {
4942 return false;
4943 }
4944
4945 return true;
4946}
4947
4948bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4949{
4950 // Currently, all GetProgramiv queries return 1 parameter
4951 *numParams = 1;
4952
4953 Program *programObject = GetValidProgram(context, program);
4954 if (!programObject)
4955 {
4956 return false;
4957 }
4958
4959 switch (pname)
4960 {
4961 case GL_DELETE_STATUS:
4962 case GL_LINK_STATUS:
4963 case GL_VALIDATE_STATUS:
4964 case GL_INFO_LOG_LENGTH:
4965 case GL_ATTACHED_SHADERS:
4966 case GL_ACTIVE_ATTRIBUTES:
4967 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4968 case GL_ACTIVE_UNIFORMS:
4969 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4970 break;
4971
4972 case GL_PROGRAM_BINARY_LENGTH:
4973 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4974 {
4975 context->handleError(Error(GL_INVALID_ENUM,
4976 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4977 "GL_OES_get_program_binary or ES 3.0."));
4978 return false;
4979 }
4980 break;
4981
4982 case GL_ACTIVE_UNIFORM_BLOCKS:
4983 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4984 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4985 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4986 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4987 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4988 if (context->getClientMajorVersion() < 3)
4989 {
4990 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4991 return false;
4992 }
4993 break;
4994
4995 default:
4996 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4997 return false;
4998 }
4999
5000 return true;
5001}
5002
5003bool ValidateGetProgramivRobustANGLE(Context *context,
5004 GLuint program,
5005 GLenum pname,
5006 GLsizei bufSize,
5007 GLsizei *numParams)
5008{
5009 if (!ValidateRobustEntryPoint(context, bufSize))
5010 {
5011 return false;
5012 }
5013
5014 if (!ValidateGetProgramiv(context, program, pname, numParams))
5015 {
5016 return false;
5017 }
5018
5019 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5020 {
5021 return false;
5022 }
5023
5024 return true;
5025}
5026
Geoff Lang740d9022016-10-07 11:20:52 -04005027bool ValidateGetRenderbufferParameteriv(Context *context,
5028 GLenum target,
5029 GLenum pname,
5030 GLint *params)
5031{
5032 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5033}
5034
5035bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5036 GLenum target,
5037 GLenum pname,
5038 GLsizei bufSize,
5039 GLsizei *length,
5040 GLint *params)
5041{
5042 if (!ValidateRobustEntryPoint(context, bufSize))
5043 {
5044 return false;
5045 }
5046
5047 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5048 {
5049 return false;
5050 }
5051
5052 if (!ValidateRobustBufferSize(context, bufSize, *length))
5053 {
5054 return false;
5055 }
5056
5057 return true;
5058}
5059
Geoff Langd7d0ed32016-10-07 11:33:51 -04005060bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5061{
5062 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5063}
5064
5065bool ValidateGetShaderivRobustANGLE(Context *context,
5066 GLuint shader,
5067 GLenum pname,
5068 GLsizei bufSize,
5069 GLsizei *length,
5070 GLint *params)
5071{
5072 if (!ValidateRobustEntryPoint(context, bufSize))
5073 {
5074 return false;
5075 }
5076
5077 if (!ValidateGetShaderivBase(context, shader, pname, length))
5078 {
5079 return false;
5080 }
5081
5082 if (!ValidateRobustBufferSize(context, bufSize, *length))
5083 {
5084 return false;
5085 }
5086
5087 return true;
5088}
5089
Geoff Langc1984ed2016-10-07 12:41:00 -04005090bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5091{
5092 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5093}
5094
5095bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5096 GLenum target,
5097 GLenum pname,
5098 GLsizei bufSize,
5099 GLsizei *length,
5100 GLfloat *params)
5101{
5102 if (!ValidateRobustEntryPoint(context, bufSize))
5103 {
5104 return false;
5105 }
5106
5107 if (!ValidateGetTexParameterBase(context, target, pname, length))
5108 {
5109 return false;
5110 }
5111
5112 if (!ValidateRobustBufferSize(context, bufSize, *length))
5113 {
5114 return false;
5115 }
5116
5117 return true;
5118}
5119
5120bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5121{
5122 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5123}
5124
5125bool ValidateGetTexParameterivRobustANGLE(Context *context,
5126 GLenum target,
5127 GLenum pname,
5128 GLsizei bufSize,
5129 GLsizei *length,
5130 GLint *params)
5131{
5132 if (!ValidateRobustEntryPoint(context, bufSize))
5133 {
5134 return false;
5135 }
5136
5137 if (!ValidateGetTexParameterBase(context, target, pname, length))
5138 {
5139 return false;
5140 }
5141
5142 if (!ValidateRobustBufferSize(context, bufSize, *length))
5143 {
5144 return false;
5145 }
5146
5147 return true;
5148}
5149
5150bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5151{
5152 return ValidateTexParameterBase(context, target, pname, -1, &param);
5153}
5154
5155bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5156{
5157 return ValidateTexParameterBase(context, target, pname, -1, params);
5158}
5159
5160bool ValidateTexParameterfvRobustANGLE(Context *context,
5161 GLenum target,
5162 GLenum pname,
5163 GLsizei bufSize,
5164 const GLfloat *params)
5165{
5166 if (!ValidateRobustEntryPoint(context, bufSize))
5167 {
5168 return false;
5169 }
5170
5171 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5172}
5173
5174bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5175{
5176 return ValidateTexParameterBase(context, target, pname, -1, &param);
5177}
5178
5179bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5180{
5181 return ValidateTexParameterBase(context, target, pname, -1, params);
5182}
5183
5184bool ValidateTexParameterivRobustANGLE(Context *context,
5185 GLenum target,
5186 GLenum pname,
5187 GLsizei bufSize,
5188 const GLint *params)
5189{
5190 if (!ValidateRobustEntryPoint(context, bufSize))
5191 {
5192 return false;
5193 }
5194
5195 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5196}
5197
5198bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5199{
5200 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5201}
5202
5203bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5204 GLuint sampler,
5205 GLenum pname,
5206 GLuint bufSize,
5207 GLsizei *length,
5208 GLfloat *params)
5209{
5210 if (!ValidateRobustEntryPoint(context, bufSize))
5211 {
5212 return false;
5213 }
5214
5215 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5216 {
5217 return false;
5218 }
5219
5220 if (!ValidateRobustBufferSize(context, bufSize, *length))
5221 {
5222 return false;
5223 }
5224
5225 return true;
5226}
5227
5228bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5229{
5230 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5231}
5232
5233bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5234 GLuint sampler,
5235 GLenum pname,
5236 GLuint bufSize,
5237 GLsizei *length,
5238 GLint *params)
5239{
5240 if (!ValidateRobustEntryPoint(context, bufSize))
5241 {
5242 return false;
5243 }
5244
5245 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5246 {
5247 return false;
5248 }
5249
5250 if (!ValidateRobustBufferSize(context, bufSize, *length))
5251 {
5252 return false;
5253 }
5254
5255 return true;
5256}
5257
5258bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5259{
5260 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5261}
5262
5263bool ValidateSamplerParameterfv(Context *context,
5264 GLuint sampler,
5265 GLenum pname,
5266 const GLfloat *params)
5267{
5268 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5269}
5270
5271bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5272 GLuint sampler,
5273 GLenum pname,
5274 GLsizei bufSize,
5275 const GLfloat *params)
5276{
5277 if (!ValidateRobustEntryPoint(context, bufSize))
5278 {
5279 return false;
5280 }
5281
5282 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5283}
5284
5285bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5286{
5287 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5288}
5289
5290bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5291{
5292 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5293}
5294
5295bool ValidateSamplerParameterivRobustANGLE(Context *context,
5296 GLuint sampler,
5297 GLenum pname,
5298 GLsizei bufSize,
5299 const GLint *params)
5300{
5301 if (!ValidateRobustEntryPoint(context, bufSize))
5302 {
5303 return false;
5304 }
5305
5306 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5307}
5308
Geoff Lang0b031062016-10-13 14:30:04 -04005309bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5310{
5311 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5312}
5313
5314bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5315 GLuint index,
5316 GLenum pname,
5317 GLsizei bufSize,
5318 GLsizei *length,
5319 GLfloat *params)
5320{
5321 if (!ValidateRobustEntryPoint(context, bufSize))
5322 {
5323 return false;
5324 }
5325
5326 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5327 {
5328 return false;
5329 }
5330
5331 if (!ValidateRobustBufferSize(context, bufSize, *length))
5332 {
5333 return false;
5334 }
5335
5336 return true;
5337}
5338
5339bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5340{
5341 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5342}
5343
5344bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5345 GLuint index,
5346 GLenum pname,
5347 GLsizei bufSize,
5348 GLsizei *length,
5349 GLint *params)
5350{
5351 if (!ValidateRobustEntryPoint(context, bufSize))
5352 {
5353 return false;
5354 }
5355
5356 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5357 {
5358 return false;
5359 }
5360
5361 if (!ValidateRobustBufferSize(context, bufSize, *length))
5362 {
5363 return false;
5364 }
5365
5366 return true;
5367}
5368
5369bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5370{
5371 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5372}
5373
5374bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5375 GLuint index,
5376 GLenum pname,
5377 GLsizei bufSize,
5378 GLsizei *length,
5379 void **pointer)
5380{
5381 if (!ValidateRobustEntryPoint(context, bufSize))
5382 {
5383 return false;
5384 }
5385
5386 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5387 {
5388 return false;
5389 }
5390
5391 if (!ValidateRobustBufferSize(context, bufSize, *length))
5392 {
5393 return false;
5394 }
5395
5396 return true;
5397}
5398
5399bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5400{
5401 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5402}
5403
5404bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5405 GLuint index,
5406 GLenum pname,
5407 GLsizei bufSize,
5408 GLsizei *length,
5409 GLint *params)
5410{
5411 if (!ValidateRobustEntryPoint(context, bufSize))
5412 {
5413 return false;
5414 }
5415
5416 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5417 {
5418 return false;
5419 }
5420
5421 if (!ValidateRobustBufferSize(context, bufSize, *length))
5422 {
5423 return false;
5424 }
5425
5426 return true;
5427}
5428
5429bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5430{
5431 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5432}
5433
5434bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5435 GLuint index,
5436 GLenum pname,
5437 GLsizei bufSize,
5438 GLsizei *length,
5439 GLuint *params)
5440{
5441 if (!ValidateRobustEntryPoint(context, bufSize))
5442 {
5443 return false;
5444 }
5445
5446 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5447 {
5448 return false;
5449 }
5450
5451 if (!ValidateRobustBufferSize(context, bufSize, *length))
5452 {
5453 return false;
5454 }
5455
5456 return true;
5457}
5458
Geoff Lang6899b872016-10-14 11:30:13 -04005459bool ValidateGetActiveUniformBlockiv(Context *context,
5460 GLuint program,
5461 GLuint uniformBlockIndex,
5462 GLenum pname,
5463 GLint *params)
5464{
5465 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5466}
5467
5468bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5469 GLuint program,
5470 GLuint uniformBlockIndex,
5471 GLenum pname,
5472 GLsizei bufSize,
5473 GLsizei *length,
5474 GLint *params)
5475{
5476 if (!ValidateRobustEntryPoint(context, bufSize))
5477 {
5478 return false;
5479 }
5480
5481 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5482 {
5483 return false;
5484 }
5485
5486 if (!ValidateRobustBufferSize(context, bufSize, *length))
5487 {
5488 return false;
5489 }
5490
5491 return true;
5492}
5493
Geoff Lang0a9661f2016-10-20 10:59:20 -07005494bool ValidateGetInternalFormativ(Context *context,
5495 GLenum target,
5496 GLenum internalformat,
5497 GLenum pname,
5498 GLsizei bufSize,
5499 GLint *params)
5500{
5501 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5502 nullptr);
5503}
5504
5505bool ValidateGetInternalFormativRobustANGLE(Context *context,
5506 GLenum target,
5507 GLenum internalformat,
5508 GLenum pname,
5509 GLsizei bufSize,
5510 GLsizei *length,
5511 GLint *params)
5512{
5513 if (!ValidateRobustEntryPoint(context, bufSize))
5514 {
5515 return false;
5516 }
5517
5518 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5519 {
5520 return false;
5521 }
5522
5523 if (!ValidateRobustBufferSize(context, bufSize, *length))
5524 {
5525 return false;
5526 }
5527
5528 return true;
5529}
5530
Jamie Madillc29968b2016-01-20 11:17:23 -05005531} // namespace gl