blob: dbddbfbe52e4527d9afa563a2a47eacffda988ee [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();
Jamie Madill6163c752015-12-07 16:32:59 -05001990 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001991
He Yunchao66a41a22016-12-15 16:45:05 +08001992 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001993 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001994 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001995
Geoff Langa15472a2015-08-11 11:48:03 -04001996 for (size_t drawbufferIdx = 0;
1997 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001998 {
Geoff Langa15472a2015-08-11 11:48:03 -04001999 const FramebufferAttachment *attachment =
2000 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2001 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002002 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002003 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002004
Geoff Langb2f3d052013-08-13 12:49:27 -04002005 // The GL ES 3.0.2 spec (pg 193) states that:
2006 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002007 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2008 // as well
2009 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2010 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002011 // Changes with EXT_color_buffer_float:
2012 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002013 GLenum readComponentType = readFormat.info->componentType;
2014 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002015 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002016 readComponentType == GL_SIGNED_NORMALIZED);
2017 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2018 drawComponentType == GL_SIGNED_NORMALIZED);
2019
2020 if (extensions.colorBufferFloat)
2021 {
2022 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2023 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2024
2025 if (readFixedOrFloat != drawFixedOrFloat)
2026 {
Jamie Madill437fa652016-05-03 15:13:24 -04002027 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002028 "If the read buffer contains fixed-point or "
2029 "floating-point values, the draw buffer "
2030 "must as well."));
2031 return false;
2032 }
2033 }
2034 else if (readFixedPoint != drawFixedPoint)
2035 {
Jamie Madill437fa652016-05-03 15:13:24 -04002036 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002037 "If the read buffer contains fixed-point "
2038 "values, the draw buffer must as well."));
2039 return false;
2040 }
2041
2042 if (readComponentType == GL_UNSIGNED_INT &&
2043 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002044 {
Jamie Madill437fa652016-05-03 15:13:24 -04002045 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002046 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002047 }
2048
Jamie Madill6163c752015-12-07 16:32:59 -05002049 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002050 {
Jamie Madill437fa652016-05-03 15:13:24 -04002051 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002052 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002053 }
2054
Jamie Madilla3944d42016-07-22 22:13:26 -04002055 if (readColorBuffer->getSamples() > 0 &&
2056 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002057 {
Jamie Madill437fa652016-05-03 15:13:24 -04002058 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002059 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002060 }
2061 }
2062 }
2063
Jamie Madilla3944d42016-07-22 22:13:26 -04002064 if ((readFormat.info->componentType == GL_INT ||
2065 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2066 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002067 {
Jamie Madill437fa652016-05-03 15:13:24 -04002068 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002069 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002070 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002071 }
He Yunchao66a41a22016-12-15 16:45:05 +08002072 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2073 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2074 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2075 // situation is an application error that would lead to a crash in ANGLE.
2076 else if (drawFramebuffer->hasEnabledDrawBuffer())
2077 {
2078 context->handleError(Error(
2079 GL_INVALID_OPERATION,
2080 "Attempt to read from a missing color attachment of a complete framebuffer."));
2081 return false;
2082 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002083 }
2084
He Yunchaoced53ae2016-11-29 15:00:51 +08002085 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002086 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2087 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002088 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002089 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002090 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002091 const gl::FramebufferAttachment *readBuffer =
2092 readFramebuffer->getAttachment(attachments[i]);
2093 const gl::FramebufferAttachment *drawBuffer =
2094 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002095
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002096 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002097 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002098 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002099 {
Jamie Madill437fa652016-05-03 15:13:24 -04002100 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002101 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002102 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002103
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002104 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002105 {
Jamie Madill437fa652016-05-03 15:13:24 -04002106 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002107 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002108 }
2109 }
He Yunchao66a41a22016-12-15 16:45:05 +08002110 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2111 else if (drawBuffer)
2112 {
2113 context->handleError(Error(GL_INVALID_OPERATION,
2114 "Attempt to read from a missing depth/stencil "
2115 "attachment of a complete framebuffer."));
2116 return false;
2117 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002118 }
2119 }
2120
2121 return true;
2122}
2123
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002124bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002125 GLint x,
2126 GLint y,
2127 GLsizei width,
2128 GLsizei height,
2129 GLenum format,
2130 GLenum type,
2131 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002132{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002133 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2134}
2135
2136bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2137 GLint x,
2138 GLint y,
2139 GLsizei width,
2140 GLsizei height,
2141 GLenum format,
2142 GLenum type,
2143 GLsizei bufSize,
2144 GLsizei *length,
2145 GLvoid *pixels)
2146{
2147 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002148 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002149 return false;
2150 }
2151
Geoff Lang62fce5b2016-09-30 10:46:35 -04002152 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2153 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002154 {
Geoff Langb1196682014-07-23 13:47:29 -04002155 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002156 }
2157
Geoff Lang62fce5b2016-09-30 10:46:35 -04002158 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002159 {
Geoff Langb1196682014-07-23 13:47:29 -04002160 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002161 }
2162
Jamie Madillc29968b2016-01-20 11:17:23 -05002163 return true;
2164}
2165
2166bool ValidateReadnPixelsEXT(Context *context,
2167 GLint x,
2168 GLint y,
2169 GLsizei width,
2170 GLsizei height,
2171 GLenum format,
2172 GLenum type,
2173 GLsizei bufSize,
2174 GLvoid *pixels)
2175{
2176 if (bufSize < 0)
2177 {
Jamie Madill437fa652016-05-03 15:13:24 -04002178 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002179 return false;
2180 }
2181
Geoff Lang62fce5b2016-09-30 10:46:35 -04002182 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2183 pixels);
2184}
Jamie Madill26e91952014-03-05 15:01:27 -05002185
Geoff Lang62fce5b2016-09-30 10:46:35 -04002186bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2187 GLint x,
2188 GLint y,
2189 GLsizei width,
2190 GLsizei height,
2191 GLenum format,
2192 GLenum type,
2193 GLsizei bufSize,
2194 GLsizei *length,
2195 GLvoid *data)
2196{
2197 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002198 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002199 return false;
2200 }
2201
Geoff Lang62fce5b2016-09-30 10:46:35 -04002202 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002203 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002204 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002205 }
2206
Geoff Lang62fce5b2016-09-30 10:46:35 -04002207 if (!ValidateRobustBufferSize(context, bufSize, *length))
2208 {
2209 return false;
2210 }
2211
2212 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002213}
2214
Olli Etuaho41997e72016-03-10 13:38:39 +02002215bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002216{
2217 if (!context->getExtensions().occlusionQueryBoolean &&
2218 !context->getExtensions().disjointTimerQuery)
2219 {
Jamie Madill437fa652016-05-03 15:13:24 -04002220 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002221 return false;
2222 }
2223
Olli Etuaho41997e72016-03-10 13:38:39 +02002224 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002225}
2226
Olli Etuaho41997e72016-03-10 13:38:39 +02002227bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002228{
2229 if (!context->getExtensions().occlusionQueryBoolean &&
2230 !context->getExtensions().disjointTimerQuery)
2231 {
Jamie Madill437fa652016-05-03 15:13:24 -04002232 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002233 return false;
2234 }
2235
Olli Etuaho41997e72016-03-10 13:38:39 +02002236 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002237}
2238
2239bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002240{
2241 if (!ValidQueryType(context, target))
2242 {
Jamie Madill437fa652016-05-03 15:13:24 -04002243 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002244 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002245 }
2246
2247 if (id == 0)
2248 {
Jamie Madill437fa652016-05-03 15:13:24 -04002249 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002250 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002251 }
2252
2253 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2254 // of zero, if the active query object name for <target> is non-zero (for the
2255 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2256 // the active query for either target is non-zero), if <id> is the name of an
2257 // existing query object whose type does not match <target>, or if <id> is the
2258 // active query object name for any query type, the error INVALID_OPERATION is
2259 // generated.
2260
2261 // Ensure no other queries are active
2262 // NOTE: If other queries than occlusion are supported, we will need to check
2263 // separately that:
2264 // a) The query ID passed is not the current active query for any target/type
2265 // b) There are no active queries for the requested target (and in the case
2266 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2267 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002268
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002269 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002270 {
Jamie Madill437fa652016-05-03 15:13:24 -04002271 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002272 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002273 }
2274
2275 Query *queryObject = context->getQuery(id, true, target);
2276
2277 // check that name was obtained with glGenQueries
2278 if (!queryObject)
2279 {
Jamie Madill437fa652016-05-03 15:13:24 -04002280 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002281 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002282 }
2283
2284 // check for type mismatch
2285 if (queryObject->getType() != target)
2286 {
Jamie Madill437fa652016-05-03 15:13:24 -04002287 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002288 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002289 }
2290
2291 return true;
2292}
2293
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002294bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2295{
2296 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002297 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002298 {
Jamie Madill437fa652016-05-03 15:13:24 -04002299 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002300 return false;
2301 }
2302
2303 return ValidateBeginQueryBase(context, target, id);
2304}
2305
2306bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002307{
2308 if (!ValidQueryType(context, target))
2309 {
Jamie Madill437fa652016-05-03 15:13:24 -04002310 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002311 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002312 }
2313
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002314 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002315
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002316 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002317 {
Jamie Madill437fa652016-05-03 15:13:24 -04002318 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002319 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002320 }
2321
Jamie Madill45c785d2014-05-13 14:09:34 -04002322 return true;
2323}
2324
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002325bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2326{
2327 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002328 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002329 {
Jamie Madill437fa652016-05-03 15:13:24 -04002330 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002331 return false;
2332 }
2333
2334 return ValidateEndQueryBase(context, target);
2335}
2336
2337bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2338{
2339 if (!context->getExtensions().disjointTimerQuery)
2340 {
Jamie Madill437fa652016-05-03 15:13:24 -04002341 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002342 return false;
2343 }
2344
2345 if (target != GL_TIMESTAMP_EXT)
2346 {
Jamie Madill437fa652016-05-03 15:13:24 -04002347 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002348 return false;
2349 }
2350
2351 Query *queryObject = context->getQuery(id, true, target);
2352 if (queryObject == nullptr)
2353 {
Jamie Madill437fa652016-05-03 15:13:24 -04002354 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002355 return false;
2356 }
2357
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002358 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002359 {
Jamie Madill437fa652016-05-03 15:13:24 -04002360 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002361 return false;
2362 }
2363
2364 return true;
2365}
2366
Geoff Lang2186c382016-10-14 10:54:54 -04002367bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002368{
Geoff Lang2186c382016-10-14 10:54:54 -04002369 if (numParams)
2370 {
2371 *numParams = 0;
2372 }
2373
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002374 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2375 {
Jamie Madill437fa652016-05-03 15:13:24 -04002376 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002377 return false;
2378 }
2379
2380 switch (pname)
2381 {
2382 case GL_CURRENT_QUERY_EXT:
2383 if (target == GL_TIMESTAMP_EXT)
2384 {
Jamie Madill437fa652016-05-03 15:13:24 -04002385 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002386 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2387 return false;
2388 }
2389 break;
2390 case GL_QUERY_COUNTER_BITS_EXT:
2391 if (!context->getExtensions().disjointTimerQuery ||
2392 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2393 {
Jamie Madill437fa652016-05-03 15:13:24 -04002394 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002395 return false;
2396 }
2397 break;
2398 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002399 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002400 return false;
2401 }
2402
Geoff Lang2186c382016-10-14 10:54:54 -04002403 if (numParams)
2404 {
2405 // All queries return only one value
2406 *numParams = 1;
2407 }
2408
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002409 return true;
2410}
2411
2412bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2413{
2414 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002415 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002416 {
Jamie Madill437fa652016-05-03 15:13:24 -04002417 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002418 return false;
2419 }
2420
Geoff Lang2186c382016-10-14 10:54:54 -04002421 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002422}
2423
Geoff Lang2186c382016-10-14 10:54:54 -04002424bool ValidateGetQueryivRobustANGLE(Context *context,
2425 GLenum target,
2426 GLenum pname,
2427 GLsizei bufSize,
2428 GLsizei *length,
2429 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002430{
Geoff Lang2186c382016-10-14 10:54:54 -04002431 if (!ValidateRobustEntryPoint(context, bufSize))
2432 {
2433 return false;
2434 }
2435
2436 if (!ValidateGetQueryivBase(context, target, pname, length))
2437 {
2438 return false;
2439 }
2440
2441 if (!ValidateRobustBufferSize(context, bufSize, *length))
2442 {
2443 return false;
2444 }
2445
2446 return true;
2447}
2448
2449bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2450{
2451 if (numParams)
2452 {
2453 *numParams = 0;
2454 }
2455
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002456 Query *queryObject = context->getQuery(id, false, GL_NONE);
2457
2458 if (!queryObject)
2459 {
Jamie Madill437fa652016-05-03 15:13:24 -04002460 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002461 return false;
2462 }
2463
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002464 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002465 {
Jamie Madill437fa652016-05-03 15:13:24 -04002466 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002467 return false;
2468 }
2469
2470 switch (pname)
2471 {
2472 case GL_QUERY_RESULT_EXT:
2473 case GL_QUERY_RESULT_AVAILABLE_EXT:
2474 break;
2475
2476 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002477 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002478 return false;
2479 }
2480
Geoff Lang2186c382016-10-14 10:54:54 -04002481 if (numParams)
2482 {
2483 *numParams = 1;
2484 }
2485
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002486 return true;
2487}
2488
2489bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2490{
2491 if (!context->getExtensions().disjointTimerQuery)
2492 {
Jamie Madill437fa652016-05-03 15:13:24 -04002493 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002494 return false;
2495 }
Geoff Lang2186c382016-10-14 10:54:54 -04002496 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2497}
2498
2499bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2500 GLuint id,
2501 GLenum pname,
2502 GLsizei bufSize,
2503 GLsizei *length,
2504 GLint *params)
2505{
2506 if (!context->getExtensions().disjointTimerQuery)
2507 {
2508 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2509 return false;
2510 }
2511
2512 if (!ValidateRobustEntryPoint(context, bufSize))
2513 {
2514 return false;
2515 }
2516
2517 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2518 {
2519 return false;
2520 }
2521
2522 if (!ValidateRobustBufferSize(context, bufSize, *length))
2523 {
2524 return false;
2525 }
2526
2527 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002528}
2529
2530bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2531{
2532 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002533 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002534 {
Jamie Madill437fa652016-05-03 15:13:24 -04002535 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002536 return false;
2537 }
Geoff Lang2186c382016-10-14 10:54:54 -04002538 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2539}
2540
2541bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2542 GLuint id,
2543 GLenum pname,
2544 GLsizei bufSize,
2545 GLsizei *length,
2546 GLuint *params)
2547{
2548 if (!context->getExtensions().disjointTimerQuery &&
2549 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2550 {
2551 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2552 return false;
2553 }
2554
2555 if (!ValidateRobustEntryPoint(context, bufSize))
2556 {
2557 return false;
2558 }
2559
2560 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2561 {
2562 return false;
2563 }
2564
2565 if (!ValidateRobustBufferSize(context, bufSize, *length))
2566 {
2567 return false;
2568 }
2569
2570 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002571}
2572
2573bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2574{
2575 if (!context->getExtensions().disjointTimerQuery)
2576 {
Jamie Madill437fa652016-05-03 15:13:24 -04002577 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002578 return false;
2579 }
Geoff Lang2186c382016-10-14 10:54:54 -04002580 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2581}
2582
2583bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2584 GLuint id,
2585 GLenum pname,
2586 GLsizei bufSize,
2587 GLsizei *length,
2588 GLint64 *params)
2589{
2590 if (!context->getExtensions().disjointTimerQuery)
2591 {
2592 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2593 return false;
2594 }
2595
2596 if (!ValidateRobustEntryPoint(context, bufSize))
2597 {
2598 return false;
2599 }
2600
2601 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2602 {
2603 return false;
2604 }
2605
2606 if (!ValidateRobustBufferSize(context, bufSize, *length))
2607 {
2608 return false;
2609 }
2610
2611 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002612}
2613
2614bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2615{
2616 if (!context->getExtensions().disjointTimerQuery)
2617 {
Jamie Madill437fa652016-05-03 15:13:24 -04002618 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002619 return false;
2620 }
Geoff Lang2186c382016-10-14 10:54:54 -04002621 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2622}
2623
2624bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2625 GLuint id,
2626 GLenum pname,
2627 GLsizei bufSize,
2628 GLsizei *length,
2629 GLuint64 *params)
2630{
2631 if (!context->getExtensions().disjointTimerQuery)
2632 {
2633 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2634 return false;
2635 }
2636
2637 if (!ValidateRobustEntryPoint(context, bufSize))
2638 {
2639 return false;
2640 }
2641
2642 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2643 {
2644 return false;
2645 }
2646
2647 if (!ValidateRobustBufferSize(context, bufSize, *length))
2648 {
2649 return false;
2650 }
2651
2652 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002653}
2654
Jamie Madill62d31cb2015-09-11 13:25:51 -04002655static bool ValidateUniformCommonBase(gl::Context *context,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002656 gl::Program *program,
Jamie Madill62d31cb2015-09-11 13:25:51 -04002657 GLenum targetUniformType,
2658 GLint location,
2659 GLsizei count,
2660 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002661{
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002662 // TODO(Jiajia): Add image uniform check in future.
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002663 if (count < 0)
2664 {
Jamie Madill437fa652016-05-03 15:13:24 -04002665 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002666 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002667 }
2668
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002669 if (!program || !program->isLinked())
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002670 {
Jamie Madill437fa652016-05-03 15:13:24 -04002671 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002672 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002673 }
2674
Geoff Langd8605522016-04-13 10:19:12 -04002675 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002676 {
2677 // Silently ignore the uniform command
2678 return false;
2679 }
2680
Geoff Lang7dd2e102014-11-10 15:19:26 -05002681 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002682 {
Jamie Madill437fa652016-05-03 15:13:24 -04002683 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002684 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002685 }
2686
Jamie Madill62d31cb2015-09-11 13:25:51 -04002687 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002688
2689 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002690 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002691 {
Jamie Madill437fa652016-05-03 15:13:24 -04002692 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002693 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002694 }
2695
Jamie Madill62d31cb2015-09-11 13:25:51 -04002696 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002697 return true;
2698}
2699
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002700bool ValidateProgramUniform(gl::Context *context,
2701 GLenum uniformType,
2702 GLuint program,
2703 GLint location,
2704 GLsizei count)
2705{
2706 // Check for ES31 program uniform entry points
2707 if (context->getClientVersion() < Version(3, 1))
2708 {
2709 context->handleError(Error(GL_INVALID_OPERATION));
2710 return false;
2711 }
2712
2713 const LinkedUniform *uniform = nullptr;
2714 gl::Program *programObject = GetValidProgram(context, program);
2715 if (!ValidateUniformCommonBase(context, programObject, uniformType, location, count, &uniform))
2716 {
2717 return false;
2718 }
2719
2720 GLenum targetBoolType = VariableBoolVectorType(uniformType);
2721 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
2722 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2723 {
2724 context->handleError(Error(GL_INVALID_OPERATION));
2725 return false;
2726 }
2727
2728 return true;
2729}
2730
2731bool ValidateProgramUniformMatrix(gl::Context *context,
2732 GLenum matrixType,
2733 GLuint program,
2734 GLint location,
2735 GLsizei count,
2736 GLboolean transpose)
2737{
2738 // Check for ES31 program uniform entry points
2739 if (context->getClientVersion() < Version(3, 1))
2740 {
2741 context->handleError(Error(GL_INVALID_OPERATION));
2742 return false;
2743 }
2744
2745 const LinkedUniform *uniform = nullptr;
2746 gl::Program *programObject = GetValidProgram(context, program);
2747 if (!ValidateUniformCommonBase(context, programObject, matrixType, location, count, &uniform))
2748 {
2749 return false;
2750 }
2751
2752 if (uniform->type != matrixType)
2753 {
2754 context->handleError(Error(GL_INVALID_OPERATION));
2755 return false;
2756 }
2757
2758 return true;
2759}
2760
Jamie Madillaa981bd2014-05-20 10:55:55 -04002761bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2762{
2763 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002764 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2765 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002766 {
Jamie Madill437fa652016-05-03 15:13:24 -04002767 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002768 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002769 }
2770
Jamie Madill62d31cb2015-09-11 13:25:51 -04002771 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002772 gl::Program *program = context->getGLState().getProgram();
2773 if (!ValidateUniformCommonBase(context, program, uniformType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002774 {
2775 return false;
2776 }
2777
He Yunchaoced53ae2016-11-29 15:00:51 +08002778 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002779 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002780 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2781 {
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 Madill36398922014-05-20 14:51:53 -04002784 }
2785
2786 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002787}
2788
He Yunchaoced53ae2016-11-29 15:00:51 +08002789bool ValidateUniformMatrix(gl::Context *context,
2790 GLenum matrixType,
2791 GLint location,
2792 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002793 GLboolean transpose)
2794{
2795 // Check for ES3 uniform entry points
2796 int rows = VariableRowCount(matrixType);
2797 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002798 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002799 {
Jamie Madill437fa652016-05-03 15:13:24 -04002800 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002801 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002802 }
2803
Martin Radev1be913c2016-07-11 17:59:16 +03002804 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002805 {
Jamie Madill437fa652016-05-03 15:13:24 -04002806 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002807 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002808 }
2809
Jamie Madill62d31cb2015-09-11 13:25:51 -04002810 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002811 gl::Program *program = context->getGLState().getProgram();
2812 if (!ValidateUniformCommonBase(context, program, matrixType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002813 {
2814 return false;
2815 }
2816
2817 if (uniform->type != matrixType)
2818 {
Jamie Madill437fa652016-05-03 15:13:24 -04002819 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002820 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002821 }
2822
2823 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002824}
2825
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002826bool ValidateStateQuery(ValidationContext *context,
2827 GLenum pname,
2828 GLenum *nativeType,
2829 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002830{
2831 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2832 {
Jamie Madill437fa652016-05-03 15:13:24 -04002833 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002834 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002835 }
2836
Jamie Madill0af26e12015-03-05 19:54:33 -05002837 const Caps &caps = context->getCaps();
2838
Jamie Madill893ab082014-05-16 16:56:10 -04002839 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2840 {
2841 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2842
Jamie Madill0af26e12015-03-05 19:54:33 -05002843 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002844 {
Jamie Madill437fa652016-05-03 15:13:24 -04002845 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002846 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002847 }
2848 }
2849
2850 switch (pname)
2851 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002852 case GL_TEXTURE_BINDING_2D:
2853 case GL_TEXTURE_BINDING_CUBE_MAP:
2854 case GL_TEXTURE_BINDING_3D:
2855 case GL_TEXTURE_BINDING_2D_ARRAY:
2856 break;
2857 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2858 if (!context->getExtensions().eglStreamConsumerExternal &&
2859 !context->getExtensions().eglImageExternal)
2860 {
2861 context->handleError(Error(GL_INVALID_ENUM,
2862 "Neither NV_EGL_stream_consumer_external nor "
2863 "GL_OES_EGL_image_external extensions enabled"));
2864 return false;
2865 }
2866 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002867
He Yunchaoced53ae2016-11-29 15:00:51 +08002868 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2869 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002870 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002871 if (context->getGLState().getReadFramebuffer()->checkStatus(
2872 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002873 {
Jamie Madill437fa652016-05-03 15:13:24 -04002874 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002875 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002876 }
2877
Jamie Madill51f40ec2016-06-15 14:06:00 -04002878 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2879 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002880
2881 if (framebuffer->getReadBufferState() == GL_NONE)
2882 {
2883 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2884 return false;
2885 }
2886
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002887 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002888 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002889 {
Jamie Madill437fa652016-05-03 15:13:24 -04002890 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002891 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002892 }
2893 }
2894 break;
2895
He Yunchaoced53ae2016-11-29 15:00:51 +08002896 default:
2897 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002898 }
2899
2900 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002901 if (*numParams == 0)
2902 {
2903 return false;
2904 }
2905
2906 return true;
2907}
2908
2909bool ValidateRobustStateQuery(ValidationContext *context,
2910 GLenum pname,
2911 GLsizei bufSize,
2912 GLenum *nativeType,
2913 unsigned int *numParams)
2914{
2915 if (!ValidateRobustEntryPoint(context, bufSize))
2916 {
2917 return false;
2918 }
2919
2920 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2921 {
2922 return false;
2923 }
2924
2925 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002926 {
2927 return false;
2928 }
2929
2930 return true;
2931}
2932
Jamie Madillc29968b2016-01-20 11:17:23 -05002933bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2934 GLenum target,
2935 GLint level,
2936 GLenum internalformat,
2937 bool isSubImage,
2938 GLint xoffset,
2939 GLint yoffset,
2940 GLint zoffset,
2941 GLint x,
2942 GLint y,
2943 GLsizei width,
2944 GLsizei height,
2945 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002946 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002947{
Jamie Madill560a8d82014-05-21 13:06:20 -04002948 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2949 {
Jamie Madill437fa652016-05-03 15:13:24 -04002950 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002951 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002952 }
2953
He Yunchaoced53ae2016-11-29 15:00:51 +08002954 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2955 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002956 {
Jamie Madill437fa652016-05-03 15:13:24 -04002957 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002958 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002959 }
2960
2961 if (border != 0)
2962 {
Jamie Madill437fa652016-05-03 15:13:24 -04002963 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002964 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002965 }
2966
2967 if (!ValidMipLevel(context, target, level))
2968 {
Jamie Madill437fa652016-05-03 15:13:24 -04002969 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002970 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002971 }
2972
Jamie Madill51f40ec2016-06-15 14:06:00 -04002973 const auto &state = context->getGLState();
2974 auto readFramebuffer = state.getReadFramebuffer();
2975 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002976 {
Jamie Madill437fa652016-05-03 15:13:24 -04002977 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002978 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002979 }
2980
Jamie Madill51f40ec2016-06-15 14:06:00 -04002981 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002982 {
Jamie Madill437fa652016-05-03 15:13:24 -04002983 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002984 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002985 }
2986
Martin Radev138064f2016-07-15 12:03:41 +03002987 if (readFramebuffer->getReadBufferState() == GL_NONE)
2988 {
2989 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2990 return false;
2991 }
2992
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002993 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2994 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002995 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002996 // situation is an application error that would lead to a crash in ANGLE.
2997 if (readFramebuffer->getReadColorbuffer() == nullptr)
2998 {
2999 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3000 return false;
3001 }
3002
Geoff Langaae65a42014-05-26 12:43:44 -04003003 const gl::Caps &caps = context->getCaps();
3004
Geoff Langaae65a42014-05-26 12:43:44 -04003005 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003006 switch (target)
3007 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003008 case GL_TEXTURE_2D:
3009 maxDimension = caps.max2DTextureSize;
3010 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003011
He Yunchaoced53ae2016-11-29 15:00:51 +08003012 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3013 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3014 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3015 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3016 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3017 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3018 maxDimension = caps.maxCubeMapTextureSize;
3019 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003020
He Yunchaoced53ae2016-11-29 15:00:51 +08003021 case GL_TEXTURE_2D_ARRAY:
3022 maxDimension = caps.max2DTextureSize;
3023 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003024
He Yunchaoced53ae2016-11-29 15:00:51 +08003025 case GL_TEXTURE_3D:
3026 maxDimension = caps.max3DTextureSize;
3027 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003028
He Yunchaoced53ae2016-11-29 15:00:51 +08003029 default:
3030 context->handleError(Error(GL_INVALID_ENUM));
3031 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003032 }
3033
Jamie Madillc29968b2016-01-20 11:17:23 -05003034 gl::Texture *texture =
3035 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003036 if (!texture)
3037 {
Jamie Madill437fa652016-05-03 15:13:24 -04003038 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003039 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003040 }
3041
Geoff Lang69cce582015-09-17 13:20:36 -04003042 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003043 {
Jamie Madill437fa652016-05-03 15:13:24 -04003044 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003045 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003046 }
3047
Geoff Lang5d601382014-07-22 15:14:06 -04003048 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3049
3050 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003051 {
Jamie Madill437fa652016-05-03 15:13:24 -04003052 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003053 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003054 }
3055
Geoff Langa9be0dc2014-12-17 12:34:40 -05003056 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003057 {
Jamie Madill437fa652016-05-03 15:13:24 -04003058 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003059 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003060 }
3061
3062 if (isSubImage)
3063 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003064 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3065 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3066 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003067 {
Jamie Madill437fa652016-05-03 15:13:24 -04003068 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003069 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003070 }
3071 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003072 else
3073 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003074 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003075 {
Jamie Madill437fa652016-05-03 15:13:24 -04003076 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003077 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003078 }
3079
Geoff Langeb66a6e2016-10-31 13:06:12 -04003080 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003081 {
Jamie Madill437fa652016-05-03 15:13:24 -04003082 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003083 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003084 }
3085
3086 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003087 if (static_cast<int>(width) > maxLevelDimension ||
3088 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003089 {
Jamie Madill437fa652016-05-03 15:13:24 -04003090 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003091 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003092 }
3093 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003094
Jamie Madill0c8abca2016-07-22 20:21:26 -04003095 if (textureFormatOut)
3096 {
3097 *textureFormatOut = texture->getFormat(target, level);
3098 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003099 return true;
3100}
3101
Jiajia Qind9671222016-11-29 16:30:31 +08003102bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003103{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003104 switch (mode)
3105 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003106 case GL_POINTS:
3107 case GL_LINES:
3108 case GL_LINE_LOOP:
3109 case GL_LINE_STRIP:
3110 case GL_TRIANGLES:
3111 case GL_TRIANGLE_STRIP:
3112 case GL_TRIANGLE_FAN:
3113 break;
3114 default:
3115 context->handleError(Error(GL_INVALID_ENUM));
3116 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003117 }
3118
Jamie Madill250d33f2014-06-06 17:09:03 -04003119 if (count < 0)
3120 {
Jamie Madill437fa652016-05-03 15:13:24 -04003121 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003122 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003123 }
3124
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003125 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003126
Jamie Madill250d33f2014-06-06 17:09:03 -04003127 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003128 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003129 {
Jamie Madill437fa652016-05-03 15:13:24 -04003130 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003131 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003132 }
3133
Jamie Madillcbcde722017-01-06 14:50:00 -05003134 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3135 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003136 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003137 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3138 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003139 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003140 const FramebufferAttachment *dsAttachment =
3141 framebuffer->getStencilOrDepthStencilAttachment();
3142 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003143 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003144 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003145
3146 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3147 bool differentWritemasks =
3148 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3149 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3150 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3151 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3152
3153 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003154 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003155 if (!context->getExtensions().webglCompatibility)
3156 {
3157 ERR("This ANGLE implementation does not support separate front/back stencil "
3158 "writemasks, reference values, or stencil mask values.");
3159 }
Jamie Madill437fa652016-05-03 15:13:24 -04003160 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003161 return false;
3162 }
Jamie Madillac528012014-06-20 13:21:23 -04003163 }
3164
Jamie Madill51f40ec2016-06-15 14:06:00 -04003165 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003166 {
Jamie Madill437fa652016-05-03 15:13:24 -04003167 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003168 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003169 }
3170
Geoff Lang7dd2e102014-11-10 15:19:26 -05003171 gl::Program *program = state.getProgram();
3172 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003173 {
Jamie Madill437fa652016-05-03 15:13:24 -04003174 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003175 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003176 }
3177
Geoff Lang7dd2e102014-11-10 15:19:26 -05003178 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003179 {
Jamie Madill437fa652016-05-03 15:13:24 -04003180 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003181 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003182 }
3183
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003184 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003185 for (unsigned int uniformBlockIndex = 0;
3186 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003187 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003188 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003189 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003190 const OffsetBindingPointer<Buffer> &uniformBuffer =
3191 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003192
Geoff Lang5d124a62015-09-15 13:03:27 -04003193 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003194 {
3195 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003196 context->handleError(
3197 Error(GL_INVALID_OPERATION,
3198 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003199 return false;
3200 }
3201
Geoff Lang5d124a62015-09-15 13:03:27 -04003202 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003203 if (uniformBufferSize == 0)
3204 {
3205 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003206 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003207 }
3208
Jamie Madill62d31cb2015-09-11 13:25:51 -04003209 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003210 {
3211 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003212 context->handleError(
3213 Error(GL_INVALID_OPERATION,
3214 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003215 return false;
3216 }
3217 }
3218
Jamie Madill250d33f2014-06-06 17:09:03 -04003219 // No-op if zero count
3220 return (count > 0);
3221}
3222
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003223bool ValidateDrawArrays(ValidationContext *context,
3224 GLenum mode,
3225 GLint first,
3226 GLsizei count,
3227 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003228{
Jamie Madillfd716582014-06-06 17:09:04 -04003229 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003230 {
Jamie Madill437fa652016-05-03 15:13:24 -04003231 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003232 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003233 }
3234
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003235 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003236 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003237 if (curTransformFeedback && curTransformFeedback->isActive() &&
3238 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003239 {
3240 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003241 // that does not match the current transform feedback object's draw mode (if transform
3242 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003243 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003244 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003245 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003246 }
3247
Jiajia Qind9671222016-11-29 16:30:31 +08003248 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003249 {
3250 return false;
3251 }
3252
Corentin Wallez71168a02016-12-19 15:11:18 -08003253 // Check the computation of maxVertex doesn't overflow.
3254 // - first < 0 or count < 0 have been checked as an error condition
3255 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3256 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3257 ASSERT(count > 0 && first >= 0);
3258 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3259 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003260 {
3261 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3262 return false;
3263 }
3264
Corentin Wallez71168a02016-12-19 15:11:18 -08003265 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003266 {
3267 return false;
3268 }
3269
3270 return true;
3271}
3272
He Yunchaoced53ae2016-11-29 15:00:51 +08003273bool ValidateDrawArraysInstanced(Context *context,
3274 GLenum mode,
3275 GLint first,
3276 GLsizei count,
3277 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003278{
3279 if (primcount < 0)
3280 {
Jamie Madill437fa652016-05-03 15:13:24 -04003281 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003282 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003283 }
3284
Jamie Madill2b976812014-08-25 15:47:49 -04003285 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003286 {
3287 return false;
3288 }
3289
3290 // No-op if zero primitive count
3291 return (primcount > 0);
3292}
3293
Geoff Lang87a93302014-09-16 13:29:43 -04003294static bool ValidateDrawInstancedANGLE(Context *context)
3295{
3296 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003297 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003298
Geoff Lang7dd2e102014-11-10 15:19:26 -05003299 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003300
3301 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003302 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003303 {
3304 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003305 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003306 {
3307 return true;
3308 }
3309 }
3310
Jamie Madill437fa652016-05-03 15:13:24 -04003311 context->handleError(Error(GL_INVALID_OPERATION,
3312 "ANGLE_instanced_arrays requires that at least one active attribute"
3313 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003314 return false;
3315}
3316
He Yunchaoced53ae2016-11-29 15:00:51 +08003317bool ValidateDrawArraysInstancedANGLE(Context *context,
3318 GLenum mode,
3319 GLint first,
3320 GLsizei count,
3321 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003322{
3323 if (!ValidateDrawInstancedANGLE(context))
3324 {
3325 return false;
3326 }
3327
3328 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3329}
3330
Jiajia Qind9671222016-11-29 16:30:31 +08003331bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003332{
Jamie Madill250d33f2014-06-06 17:09:03 -04003333 switch (type)
3334 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003335 case GL_UNSIGNED_BYTE:
3336 case GL_UNSIGNED_SHORT:
3337 break;
3338 case GL_UNSIGNED_INT:
3339 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3340 {
3341 context->handleError(Error(GL_INVALID_ENUM));
3342 return false;
3343 }
3344 break;
3345 default:
3346 context->handleError(Error(GL_INVALID_ENUM));
3347 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003348 }
3349
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003350 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003351
3352 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003353 if (curTransformFeedback && curTransformFeedback->isActive() &&
3354 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003355 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003356 // It is an invalid operation to call DrawElements, DrawRangeElements or
3357 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003358 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003359 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003360 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003361 }
3362
Jiajia Qind9671222016-11-29 16:30:31 +08003363 return true;
3364}
3365
3366bool ValidateDrawElements(ValidationContext *context,
3367 GLenum mode,
3368 GLsizei count,
3369 GLenum type,
3370 const GLvoid *indices,
3371 GLsizei primcount,
3372 IndexRange *indexRangeOut)
3373{
3374 if (!ValidateDrawElementsBase(context, type))
3375 return false;
3376
3377 const State &state = context->getGLState();
3378
Jamie Madill250d33f2014-06-06 17:09:03 -04003379 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003380 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003381 {
Jamie Madill437fa652016-05-03 15:13:24 -04003382 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003383 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003384 }
3385
He Yunchaoced53ae2016-11-29 15:00:51 +08003386 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003387 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003388
Jamie Madillae3000b2014-08-25 15:47:51 -04003389 if (elementArrayBuffer)
3390 {
3391 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3392
3393 GLint64 offset = reinterpret_cast<GLint64>(indices);
He Yunchaoced53ae2016-11-29 15:00:51 +08003394 GLint64 byteCount =
3395 static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count) + offset;
Jamie Madillae3000b2014-08-25 15:47:51 -04003396
3397 // check for integer overflows
3398 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3399 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3400 {
Jamie Madill437fa652016-05-03 15:13:24 -04003401 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003402 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003403 }
3404
3405 // Check for reading past the end of the bound buffer object
3406 if (byteCount > elementArrayBuffer->getSize())
3407 {
Jamie Madill437fa652016-05-03 15:13:24 -04003408 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003409 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003410 }
3411 }
Corentin Wallez327411e2016-12-09 11:09:17 -05003412 else if (context->getExtensions().webglCompatibility && count > 0)
3413 {
3414 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3415 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3416 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3417 context->handleError(
3418 Error(GL_INVALID_OPERATION, "There is no element array buffer bound and count > 0."));
3419 return false;
3420 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003421 else if (!indices)
3422 {
Corentin Wallez327411e2016-12-09 11:09:17 -05003423 // This is an application error that would normally result in a crash,
3424 // but we catch it and return an error
3425 context->handleError(
3426 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003427 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003428 }
3429
Jiajia Qind9671222016-11-29 16:30:31 +08003430 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003431 {
3432 return false;
3433 }
3434
Jamie Madill2b976812014-08-25 15:47:49 -04003435 // Use max index to validate if our vertex buffers are large enough for the pull.
3436 // TODO: offer fast path, with disabled index validation.
3437 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3438 if (elementArrayBuffer)
3439 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003440 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003441 Error error =
3442 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3443 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003444 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003445 {
Jamie Madill437fa652016-05-03 15:13:24 -04003446 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003447 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003448 }
3449 }
3450 else
3451 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003452 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003453 }
3454
Jamie Madille79b1e12015-11-04 16:36:37 -05003455 // If we use an index greater than our maximum supported index range, return an error.
3456 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3457 // return an error if possible here.
3458 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3459 {
Jamie Madill437fa652016-05-03 15:13:24 -04003460 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003461 return false;
3462 }
3463
Corentin Wallez92db6942016-12-09 13:10:36 -05003464 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3465 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003466 {
3467 return false;
3468 }
3469
Geoff Lang3edfe032015-09-04 16:38:24 -04003470 // No op if there are no real indices in the index data (all are primitive restart).
3471 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003472}
3473
Geoff Langb1196682014-07-23 13:47:29 -04003474bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003475 GLenum mode,
3476 GLsizei count,
3477 GLenum type,
3478 const GLvoid *indices,
3479 GLsizei primcount,
3480 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003481{
3482 if (primcount < 0)
3483 {
Jamie Madill437fa652016-05-03 15:13:24 -04003484 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003485 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003486 }
3487
Jamie Madill2b976812014-08-25 15:47:49 -04003488 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003489 {
3490 return false;
3491 }
3492
3493 // No-op zero primitive count
3494 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003495}
3496
Geoff Lang3edfe032015-09-04 16:38:24 -04003497bool ValidateDrawElementsInstancedANGLE(Context *context,
3498 GLenum mode,
3499 GLsizei count,
3500 GLenum type,
3501 const GLvoid *indices,
3502 GLsizei primcount,
3503 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003504{
3505 if (!ValidateDrawInstancedANGLE(context))
3506 {
3507 return false;
3508 }
3509
He Yunchaoced53ae2016-11-29 15:00:51 +08003510 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3511 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003512}
3513
He Yunchaoced53ae2016-11-29 15:00:51 +08003514bool ValidateFramebufferTextureBase(Context *context,
3515 GLenum target,
3516 GLenum attachment,
3517 GLuint texture,
3518 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003519{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003520 if (!ValidFramebufferTarget(target))
3521 {
Jamie Madill437fa652016-05-03 15:13:24 -04003522 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003523 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003524 }
3525
3526 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003527 {
3528 return false;
3529 }
3530
Jamie Madill55ec3b12014-07-03 10:38:57 -04003531 if (texture != 0)
3532 {
3533 gl::Texture *tex = context->getTexture(texture);
3534
3535 if (tex == NULL)
3536 {
Jamie Madill437fa652016-05-03 15:13:24 -04003537 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003538 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003539 }
3540
3541 if (level < 0)
3542 {
Jamie Madill437fa652016-05-03 15:13:24 -04003543 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003544 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003545 }
3546 }
3547
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003548 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003549 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003550
Jamie Madill84115c92015-04-23 15:00:07 -04003551 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003552 {
Jamie Madill437fa652016-05-03 15:13:24 -04003553 context->handleError(
3554 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003555 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003556 }
3557
3558 return true;
3559}
3560
He Yunchaoced53ae2016-11-29 15:00:51 +08003561bool ValidateFramebufferTexture2D(Context *context,
3562 GLenum target,
3563 GLenum attachment,
3564 GLenum textarget,
3565 GLuint texture,
3566 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003567{
He Yunchaoced53ae2016-11-29 15:00:51 +08003568 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3569 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003570 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3571 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003572 {
Jamie Madill437fa652016-05-03 15:13:24 -04003573 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003574 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003575 }
3576
3577 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003578 {
3579 return false;
3580 }
3581
Jamie Madill55ec3b12014-07-03 10:38:57 -04003582 if (texture != 0)
3583 {
3584 gl::Texture *tex = context->getTexture(texture);
3585 ASSERT(tex);
3586
Jamie Madill2a6564e2014-07-11 09:53:19 -04003587 const gl::Caps &caps = context->getCaps();
3588
Jamie Madill55ec3b12014-07-03 10:38:57 -04003589 switch (textarget)
3590 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003591 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003592 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003593 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003594 {
Jamie Madill437fa652016-05-03 15:13:24 -04003595 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003596 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003597 }
3598 if (tex->getTarget() != GL_TEXTURE_2D)
3599 {
Jamie Madill437fa652016-05-03 15:13:24 -04003600 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003601 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003602 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003603 }
3604 break;
3605
He Yunchaoced53ae2016-11-29 15:00:51 +08003606 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3607 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3608 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3609 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3610 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3611 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003612 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003613 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003614 {
Jamie Madill437fa652016-05-03 15:13:24 -04003615 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003616 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003617 }
3618 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3619 {
Jamie Madill437fa652016-05-03 15:13:24 -04003620 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003621 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003622 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003623 }
3624 break;
3625
He Yunchaoced53ae2016-11-29 15:00:51 +08003626 default:
3627 context->handleError(Error(GL_INVALID_ENUM));
3628 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003629 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003630
Jamie Madilla3944d42016-07-22 22:13:26 -04003631 const Format &format = tex->getFormat(textarget, level);
3632 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003633 {
Jamie Madill437fa652016-05-03 15:13:24 -04003634 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003635 return false;
3636 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003637 }
3638
Jamie Madill570f7c82014-07-03 10:38:54 -04003639 return true;
3640}
3641
Geoff Langb1196682014-07-23 13:47:29 -04003642bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003643{
3644 if (program == 0)
3645 {
Jamie Madill437fa652016-05-03 15:13:24 -04003646 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003647 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003648 }
3649
Dian Xiang769769a2015-09-09 15:20:08 -07003650 gl::Program *programObject = GetValidProgram(context, program);
3651 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003652 {
3653 return false;
3654 }
3655
Jamie Madill0063c512014-08-25 15:47:53 -04003656 if (!programObject || !programObject->isLinked())
3657 {
Jamie Madill437fa652016-05-03 15:13:24 -04003658 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003659 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003660 }
3661
Geoff Lang7dd2e102014-11-10 15:19:26 -05003662 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003663 {
Jamie Madill437fa652016-05-03 15:13:24 -04003664 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003665 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003666 }
3667
Jamie Madill0063c512014-08-25 15:47:53 -04003668 return true;
3669}
3670
He Yunchaoced53ae2016-11-29 15:00:51 +08003671bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003672{
3673 return ValidateGetUniformBase(context, program, location);
3674}
3675
He Yunchaoced53ae2016-11-29 15:00:51 +08003676bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003677{
Jamie Madill78f41802014-08-25 15:47:55 -04003678 return ValidateGetUniformBase(context, program, location);
3679}
3680
Geoff Langf41d0ee2016-10-07 13:04:23 -04003681static bool ValidateSizedGetUniform(Context *context,
3682 GLuint program,
3683 GLint location,
3684 GLsizei bufSize,
3685 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003686{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003687 if (length)
3688 {
3689 *length = 0;
3690 }
3691
Jamie Madill78f41802014-08-25 15:47:55 -04003692 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003693 {
Jamie Madill78f41802014-08-25 15:47:55 -04003694 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003695 }
3696
Geoff Langf41d0ee2016-10-07 13:04:23 -04003697 if (bufSize < 0)
3698 {
3699 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3700 return false;
3701 }
3702
Jamie Madilla502c742014-08-28 17:19:13 -04003703 gl::Program *programObject = context->getProgram(program);
3704 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003705
Jamie Madill78f41802014-08-25 15:47:55 -04003706 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003707 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003708 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003709 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003710 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003711 context->handleError(
3712 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003713 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003714 }
3715
Geoff Langf41d0ee2016-10-07 13:04:23 -04003716 if (length)
3717 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003718 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003719 }
3720
Jamie Madill0063c512014-08-25 15:47:53 -04003721 return true;
3722}
3723
He Yunchaoced53ae2016-11-29 15:00:51 +08003724bool ValidateGetnUniformfvEXT(Context *context,
3725 GLuint program,
3726 GLint location,
3727 GLsizei bufSize,
3728 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003729{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003730 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003731}
3732
He Yunchaoced53ae2016-11-29 15:00:51 +08003733bool ValidateGetnUniformivEXT(Context *context,
3734 GLuint program,
3735 GLint location,
3736 GLsizei bufSize,
3737 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003738{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003739 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3740}
3741
3742bool ValidateGetUniformfvRobustANGLE(Context *context,
3743 GLuint program,
3744 GLint location,
3745 GLsizei bufSize,
3746 GLsizei *length,
3747 GLfloat *params)
3748{
3749 if (!ValidateRobustEntryPoint(context, bufSize))
3750 {
3751 return false;
3752 }
3753
3754 // bufSize is validated in ValidateSizedGetUniform
3755 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3756}
3757
3758bool ValidateGetUniformivRobustANGLE(Context *context,
3759 GLuint program,
3760 GLint location,
3761 GLsizei bufSize,
3762 GLsizei *length,
3763 GLint *params)
3764{
3765 if (!ValidateRobustEntryPoint(context, bufSize))
3766 {
3767 return false;
3768 }
3769
3770 // bufSize is validated in ValidateSizedGetUniform
3771 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3772}
3773
3774bool ValidateGetUniformuivRobustANGLE(Context *context,
3775 GLuint program,
3776 GLint location,
3777 GLsizei bufSize,
3778 GLsizei *length,
3779 GLuint *params)
3780{
3781 if (!ValidateRobustEntryPoint(context, bufSize))
3782 {
3783 return false;
3784 }
3785
3786 if (context->getClientMajorVersion() < 3)
3787 {
3788 context->handleError(
3789 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3790 return false;
3791 }
3792
3793 // bufSize is validated in ValidateSizedGetUniform
3794 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003795}
3796
He Yunchaoced53ae2016-11-29 15:00:51 +08003797bool ValidateDiscardFramebufferBase(Context *context,
3798 GLenum target,
3799 GLsizei numAttachments,
3800 const GLenum *attachments,
3801 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003802{
3803 if (numAttachments < 0)
3804 {
Jamie Madill437fa652016-05-03 15:13:24 -04003805 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003806 return false;
3807 }
3808
3809 for (GLsizei i = 0; i < numAttachments; ++i)
3810 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003811 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003812 {
3813 if (defaultFramebuffer)
3814 {
Jamie Madill437fa652016-05-03 15:13:24 -04003815 context->handleError(Error(
3816 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003817 return false;
3818 }
3819
3820 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3821 {
Jamie Madill437fa652016-05-03 15:13:24 -04003822 context->handleError(Error(GL_INVALID_OPERATION,
3823 "Requested color attachment is greater than the maximum "
3824 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003825 return false;
3826 }
3827 }
3828 else
3829 {
3830 switch (attachments[i])
3831 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003832 case GL_DEPTH_ATTACHMENT:
3833 case GL_STENCIL_ATTACHMENT:
3834 case GL_DEPTH_STENCIL_ATTACHMENT:
3835 if (defaultFramebuffer)
3836 {
3837 context->handleError(
3838 Error(GL_INVALID_ENUM,
3839 "Invalid attachment when the default framebuffer is bound"));
3840 return false;
3841 }
3842 break;
3843 case GL_COLOR:
3844 case GL_DEPTH:
3845 case GL_STENCIL:
3846 if (!defaultFramebuffer)
3847 {
3848 context->handleError(
3849 Error(GL_INVALID_ENUM,
3850 "Invalid attachment when the default framebuffer is not bound"));
3851 return false;
3852 }
3853 break;
3854 default:
3855 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003856 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003857 }
3858 }
3859 }
3860
3861 return true;
3862}
3863
Austin Kinross6ee1e782015-05-29 17:05:37 -07003864bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3865{
3866 // Note that debug marker calls must not set error state
3867
3868 if (length < 0)
3869 {
3870 return false;
3871 }
3872
3873 if (marker == nullptr)
3874 {
3875 return false;
3876 }
3877
3878 return true;
3879}
3880
3881bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3882{
3883 // Note that debug marker calls must not set error state
3884
3885 if (length < 0)
3886 {
3887 return false;
3888 }
3889
3890 if (length > 0 && marker == nullptr)
3891 {
3892 return false;
3893 }
3894
3895 return true;
3896}
3897
Geoff Langdcab33b2015-07-21 13:03:16 -04003898bool ValidateEGLImageTargetTexture2DOES(Context *context,
3899 egl::Display *display,
3900 GLenum target,
3901 egl::Image *image)
3902{
Geoff Langa8406172015-07-21 16:53:39 -04003903 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3904 {
Jamie Madill437fa652016-05-03 15:13:24 -04003905 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003906 return false;
3907 }
3908
3909 switch (target)
3910 {
3911 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003912 if (!context->getExtensions().eglImage)
3913 {
3914 context->handleError(Error(
3915 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3916 }
3917 break;
3918
3919 case GL_TEXTURE_EXTERNAL_OES:
3920 if (!context->getExtensions().eglImageExternal)
3921 {
3922 context->handleError(Error(
3923 GL_INVALID_ENUM,
3924 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3925 }
Geoff Langa8406172015-07-21 16:53:39 -04003926 break;
3927
3928 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003929 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003930 return false;
3931 }
3932
3933 if (!display->isValidImage(image))
3934 {
Jamie Madill437fa652016-05-03 15:13:24 -04003935 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003936 return false;
3937 }
3938
3939 if (image->getSamples() > 0)
3940 {
Jamie Madill437fa652016-05-03 15:13:24 -04003941 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003942 "cannot create a 2D texture from a multisampled EGL image."));
3943 return false;
3944 }
3945
Jamie Madilla3944d42016-07-22 22:13:26 -04003946 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003947 if (!textureCaps.texturable)
3948 {
Jamie Madill437fa652016-05-03 15:13:24 -04003949 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003950 "EGL image internal format is not supported as a texture."));
3951 return false;
3952 }
3953
Geoff Langdcab33b2015-07-21 13:03:16 -04003954 return true;
3955}
3956
3957bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3958 egl::Display *display,
3959 GLenum target,
3960 egl::Image *image)
3961{
Geoff Langa8406172015-07-21 16:53:39 -04003962 if (!context->getExtensions().eglImage)
3963 {
Jamie Madill437fa652016-05-03 15:13:24 -04003964 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003965 return false;
3966 }
3967
3968 switch (target)
3969 {
3970 case GL_RENDERBUFFER:
3971 break;
3972
3973 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003974 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003975 return false;
3976 }
3977
3978 if (!display->isValidImage(image))
3979 {
Jamie Madill437fa652016-05-03 15:13:24 -04003980 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003981 return false;
3982 }
3983
Jamie Madilla3944d42016-07-22 22:13:26 -04003984 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003985 if (!textureCaps.renderable)
3986 {
Jamie Madill437fa652016-05-03 15:13:24 -04003987 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003988 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3989 return false;
3990 }
3991
Geoff Langdcab33b2015-07-21 13:03:16 -04003992 return true;
3993}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003994
3995bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3996{
Geoff Lang36167ab2015-12-07 10:27:14 -05003997 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003998 {
3999 // The default VAO should always exist
4000 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004001 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004002 return false;
4003 }
4004
4005 return true;
4006}
4007
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004008bool ValidateLinkProgram(Context *context, GLuint program)
4009{
4010 if (context->hasActiveTransformFeedback(program))
4011 {
4012 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004013 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004014 "Cannot link program while program is associated with an active "
4015 "transform feedback object."));
4016 return false;
4017 }
4018 return true;
4019}
4020
Geoff Langc5629752015-12-07 16:29:04 -05004021bool ValidateProgramBinaryBase(Context *context,
4022 GLuint program,
4023 GLenum binaryFormat,
4024 const void *binary,
4025 GLint length)
4026{
4027 Program *programObject = GetValidProgram(context, program);
4028 if (programObject == nullptr)
4029 {
4030 return false;
4031 }
4032
4033 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4034 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4035 programBinaryFormats.end())
4036 {
Jamie Madill437fa652016-05-03 15:13:24 -04004037 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004038 return false;
4039 }
4040
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004041 if (context->hasActiveTransformFeedback(program))
4042 {
4043 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004044 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004045 "Cannot change program binary while program is associated with "
4046 "an active transform feedback object."));
4047 return false;
4048 }
4049
Geoff Langc5629752015-12-07 16:29:04 -05004050 return true;
4051}
4052
4053bool ValidateGetProgramBinaryBase(Context *context,
4054 GLuint program,
4055 GLsizei bufSize,
4056 GLsizei *length,
4057 GLenum *binaryFormat,
4058 void *binary)
4059{
4060 Program *programObject = GetValidProgram(context, program);
4061 if (programObject == nullptr)
4062 {
4063 return false;
4064 }
4065
4066 if (!programObject->isLinked())
4067 {
Jamie Madill437fa652016-05-03 15:13:24 -04004068 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004069 return false;
4070 }
4071
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004072 if (context->getCaps().programBinaryFormats.empty())
4073 {
4074 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4075 return false;
4076 }
4077
Geoff Langc5629752015-12-07 16:29:04 -05004078 return true;
4079}
Jamie Madillc29968b2016-01-20 11:17:23 -05004080
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004081bool ValidateUseProgram(Context *context, GLuint program)
4082{
4083 if (program != 0)
4084 {
4085 Program *programObject = context->getProgram(program);
4086 if (!programObject)
4087 {
4088 // ES 3.1.0 section 7.3 page 72
4089 if (context->getShader(program))
4090 {
Jamie Madill437fa652016-05-03 15:13:24 -04004091 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004092 Error(GL_INVALID_OPERATION,
4093 "Attempted to use a single shader instead of a shader program."));
4094 return false;
4095 }
4096 else
4097 {
Jamie Madill437fa652016-05-03 15:13:24 -04004098 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004099 return false;
4100 }
4101 }
4102 if (!programObject->isLinked())
4103 {
Jamie Madill437fa652016-05-03 15:13:24 -04004104 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004105 return false;
4106 }
4107 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004108 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004109 {
4110 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004111 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004112 Error(GL_INVALID_OPERATION,
4113 "Cannot change active program while transform feedback is unpaused."));
4114 return false;
4115 }
4116
4117 return true;
4118}
4119
Jamie Madillc29968b2016-01-20 11:17:23 -05004120bool ValidateCopyTexImage2D(ValidationContext *context,
4121 GLenum target,
4122 GLint level,
4123 GLenum internalformat,
4124 GLint x,
4125 GLint y,
4126 GLsizei width,
4127 GLsizei height,
4128 GLint border)
4129{
Martin Radev1be913c2016-07-11 17:59:16 +03004130 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004131 {
4132 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4133 0, x, y, width, height, border);
4134 }
4135
Martin Radev1be913c2016-07-11 17:59:16 +03004136 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004137 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4138 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004139}
Jamie Madillc29968b2016-01-20 11:17:23 -05004140
4141bool ValidateFramebufferRenderbuffer(Context *context,
4142 GLenum target,
4143 GLenum attachment,
4144 GLenum renderbuffertarget,
4145 GLuint renderbuffer)
4146{
4147 if (!ValidFramebufferTarget(target) ||
4148 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4149 {
Jamie Madill437fa652016-05-03 15:13:24 -04004150 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004151 return false;
4152 }
4153
4154 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4155 renderbuffertarget, renderbuffer);
4156}
4157
4158bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4159{
4160 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4161 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4162 {
Jamie Madill437fa652016-05-03 15:13:24 -04004163 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004164 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4165 return false;
4166 }
4167
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004168 ASSERT(context->getGLState().getDrawFramebuffer());
4169 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004170 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4171
4172 // This should come first before the check for the default frame buffer
4173 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4174 // rather than INVALID_OPERATION
4175 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4176 {
4177 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4178
4179 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004180 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4181 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004182 {
4183 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004184 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4185 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4186 // 3.1 is still a bit ambiguous about the error, but future specs are
4187 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004188 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004189 return false;
4190 }
4191 else if (bufs[colorAttachment] >= maxColorAttachment)
4192 {
Jamie Madill437fa652016-05-03 15:13:24 -04004193 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004194 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004195 return false;
4196 }
4197 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4198 frameBufferId != 0)
4199 {
4200 // INVALID_OPERATION-GL is bound to buffer and ith argument
4201 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004202 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004203 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4204 return false;
4205 }
4206 }
4207
4208 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4209 // and n is not 1 or bufs is bound to value other than BACK and NONE
4210 if (frameBufferId == 0)
4211 {
4212 if (n != 1)
4213 {
Jamie Madill437fa652016-05-03 15:13:24 -04004214 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004215 "n must be 1 when GL is bound to the default framebuffer"));
4216 return false;
4217 }
4218
4219 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4220 {
Jamie Madill437fa652016-05-03 15:13:24 -04004221 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004222 GL_INVALID_OPERATION,
4223 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4224 return false;
4225 }
4226 }
4227
4228 return true;
4229}
4230
4231bool ValidateCopyTexSubImage2D(Context *context,
4232 GLenum target,
4233 GLint level,
4234 GLint xoffset,
4235 GLint yoffset,
4236 GLint x,
4237 GLint y,
4238 GLsizei width,
4239 GLsizei height)
4240{
Martin Radev1be913c2016-07-11 17:59:16 +03004241 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004242 {
4243 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4244 yoffset, x, y, width, height, 0);
4245 }
4246
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004247 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4248 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004249}
4250
Geoff Lang496c02d2016-10-20 11:38:11 -07004251bool ValidateGetBufferPointervBase(Context *context,
4252 GLenum target,
4253 GLenum pname,
4254 GLsizei *length,
4255 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004256{
Geoff Lang496c02d2016-10-20 11:38:11 -07004257 if (length)
4258 {
4259 *length = 0;
4260 }
4261
4262 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4263 {
4264 context->handleError(
4265 Error(GL_INVALID_OPERATION,
4266 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
4267 return false;
4268 }
4269
Olli Etuaho4f667482016-03-30 15:56:35 +03004270 if (!ValidBufferTarget(context, target))
4271 {
Jamie Madill437fa652016-05-03 15:13:24 -04004272 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004273 return false;
4274 }
4275
Geoff Lang496c02d2016-10-20 11:38:11 -07004276 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004277 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004278 case GL_BUFFER_MAP_POINTER:
4279 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004280
Geoff Lang496c02d2016-10-20 11:38:11 -07004281 default:
4282 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4283 return false;
4284 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004285
4286 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4287 // target bound to zero generate an INVALID_OPERATION error."
4288 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004289 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004290 {
Jamie Madill437fa652016-05-03 15:13:24 -04004291 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004292 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4293 return false;
4294 }
4295
Geoff Lang496c02d2016-10-20 11:38:11 -07004296 if (length)
4297 {
4298 *length = 1;
4299 }
4300
Olli Etuaho4f667482016-03-30 15:56:35 +03004301 return true;
4302}
4303
4304bool ValidateUnmapBufferBase(Context *context, GLenum target)
4305{
4306 if (!ValidBufferTarget(context, target))
4307 {
Jamie Madill437fa652016-05-03 15:13:24 -04004308 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004309 return false;
4310 }
4311
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004312 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004313
4314 if (buffer == nullptr || !buffer->isMapped())
4315 {
Jamie Madill437fa652016-05-03 15:13:24 -04004316 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004317 return false;
4318 }
4319
4320 return true;
4321}
4322
4323bool ValidateMapBufferRangeBase(Context *context,
4324 GLenum target,
4325 GLintptr offset,
4326 GLsizeiptr length,
4327 GLbitfield access)
4328{
4329 if (!ValidBufferTarget(context, target))
4330 {
Jamie Madill437fa652016-05-03 15:13:24 -04004331 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004332 return false;
4333 }
4334
4335 if (offset < 0 || length < 0)
4336 {
Jamie Madill437fa652016-05-03 15:13:24 -04004337 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004338 return false;
4339 }
4340
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004341 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004342
4343 if (!buffer)
4344 {
Jamie Madill437fa652016-05-03 15:13:24 -04004345 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004346 return false;
4347 }
4348
4349 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004350 CheckedNumeric<size_t> checkedOffset(offset);
4351 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004352
Jamie Madille2e406c2016-06-02 13:04:10 -04004353 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004354 {
Jamie Madill437fa652016-05-03 15:13:24 -04004355 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004356 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4357 return false;
4358 }
4359
4360 // Check for invalid bits in the mask
4361 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4362 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4363 GL_MAP_UNSYNCHRONIZED_BIT;
4364
4365 if (access & ~(allAccessBits))
4366 {
Jamie Madill437fa652016-05-03 15:13:24 -04004367 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004368 return false;
4369 }
4370
4371 if (length == 0)
4372 {
Jamie Madill437fa652016-05-03 15:13:24 -04004373 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004374 return false;
4375 }
4376
4377 if (buffer->isMapped())
4378 {
Jamie Madill437fa652016-05-03 15:13:24 -04004379 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004380 return false;
4381 }
4382
4383 // Check for invalid bit combinations
4384 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4385 {
Jamie Madill437fa652016-05-03 15:13:24 -04004386 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004387 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4388 return false;
4389 }
4390
4391 GLbitfield writeOnlyBits =
4392 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4393
4394 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4395 {
Jamie Madill437fa652016-05-03 15:13:24 -04004396 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004397 "Invalid access bits when mapping buffer for reading: 0x%X.",
4398 access));
4399 return false;
4400 }
4401
4402 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4403 {
Jamie Madill437fa652016-05-03 15:13:24 -04004404 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004405 GL_INVALID_OPERATION,
4406 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4407 return false;
4408 }
4409 return true;
4410}
4411
4412bool ValidateFlushMappedBufferRangeBase(Context *context,
4413 GLenum target,
4414 GLintptr offset,
4415 GLsizeiptr length)
4416{
4417 if (offset < 0 || length < 0)
4418 {
Jamie Madill437fa652016-05-03 15:13:24 -04004419 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004420 return false;
4421 }
4422
4423 if (!ValidBufferTarget(context, target))
4424 {
Jamie Madill437fa652016-05-03 15:13:24 -04004425 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004426 return false;
4427 }
4428
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004429 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004430
4431 if (buffer == nullptr)
4432 {
Jamie Madill437fa652016-05-03 15:13:24 -04004433 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004434 return false;
4435 }
4436
4437 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4438 {
Jamie Madill437fa652016-05-03 15:13:24 -04004439 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004440 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4441 return false;
4442 }
4443
4444 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004445 CheckedNumeric<size_t> checkedOffset(offset);
4446 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004447
Jamie Madille2e406c2016-06-02 13:04:10 -04004448 if (!checkedSize.IsValid() ||
4449 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004450 {
Jamie Madill437fa652016-05-03 15:13:24 -04004451 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004452 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4453 return false;
4454 }
4455
4456 return true;
4457}
4458
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004459bool ValidateGenerateMipmap(Context *context, GLenum target)
4460{
4461 if (!ValidTextureTarget(context, target))
4462 {
4463 context->handleError(Error(GL_INVALID_ENUM));
4464 return false;
4465 }
4466
4467 Texture *texture = context->getTargetTexture(target);
4468
4469 if (texture == nullptr)
4470 {
4471 context->handleError(Error(GL_INVALID_OPERATION));
4472 return false;
4473 }
4474
4475 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4476
4477 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4478 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4479 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4480 {
4481 context->handleError(Error(GL_INVALID_OPERATION));
4482 return false;
4483 }
4484
Jamie Madilla3944d42016-07-22 22:13:26 -04004485 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4486 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4487 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004488
4489 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4490 // unsized formats or that are color renderable and filterable. Since we do not track if
4491 // the texture was created with sized or unsized format (only sized formats are stored),
4492 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4493 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4494 // textures since they're the only texture format that can be created with unsized formats
4495 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4496 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004497 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4498 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004499 {
4500 context->handleError(Error(GL_INVALID_OPERATION));
4501 return false;
4502 }
4503
4504 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004505 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004506 {
4507 context->handleError(Error(GL_INVALID_OPERATION));
4508 return false;
4509 }
4510
4511 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004512 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004513 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4514 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4515 {
Geoff Lang55482a12016-11-21 16:54:01 -05004516 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004517 context->handleError(Error(GL_INVALID_OPERATION));
4518 return false;
4519 }
4520
4521 // Cube completeness check
4522 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4523 {
4524 context->handleError(Error(GL_INVALID_OPERATION));
4525 return false;
4526 }
4527
4528 return true;
4529}
4530
Olli Etuaho41997e72016-03-10 13:38:39 +02004531bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4532{
4533 return ValidateGenOrDelete(context, n);
4534}
4535
4536bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4537{
4538 return ValidateGenOrDelete(context, n);
4539}
4540
4541bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4542{
4543 return ValidateGenOrDelete(context, n);
4544}
4545
4546bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4547{
4548 return ValidateGenOrDelete(context, n);
4549}
4550
4551bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4552{
4553 return ValidateGenOrDelete(context, n);
4554}
4555
4556bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4557{
4558 return ValidateGenOrDelete(context, n);
4559}
4560
4561bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4562{
4563 return ValidateGenOrDelete(context, n);
4564}
4565
4566bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4567{
4568 return ValidateGenOrDelete(context, n);
4569}
4570
4571bool ValidateGenOrDelete(Context *context, GLint n)
4572{
4573 if (n < 0)
4574 {
Jamie Madill437fa652016-05-03 15:13:24 -04004575 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004576 return false;
4577 }
4578 return true;
4579}
4580
Geoff Langf41a7152016-09-19 15:11:17 -04004581bool ValidateEnable(Context *context, GLenum cap)
4582{
4583 if (!ValidCap(context, cap, false))
4584 {
4585 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4586 return false;
4587 }
4588
4589 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4590 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4591 {
4592 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4593 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4594
4595 // We also output an error message to the debugger window if tracing is active, so that
4596 // developers can see the error message.
4597 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004598 return false;
4599 }
4600
4601 return true;
4602}
4603
4604bool ValidateDisable(Context *context, GLenum cap)
4605{
4606 if (!ValidCap(context, cap, false))
4607 {
4608 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4609 return false;
4610 }
4611
4612 return true;
4613}
4614
4615bool ValidateIsEnabled(Context *context, GLenum cap)
4616{
4617 if (!ValidCap(context, cap, true))
4618 {
4619 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4620 return false;
4621 }
4622
4623 return true;
4624}
4625
Geoff Langff5b2d52016-09-07 11:32:23 -04004626bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4627{
4628 if (!context->getExtensions().robustClientMemory)
4629 {
4630 context->handleError(
4631 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4632 return false;
4633 }
4634
4635 if (bufSize < 0)
4636 {
4637 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4638 return false;
4639 }
4640
4641 return true;
4642}
4643
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004644bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4645{
4646 if (bufSize < numParams)
4647 {
4648 context->handleError(Error(GL_INVALID_OPERATION,
4649 "%u parameters are required but %i were provided.", numParams,
4650 bufSize));
4651 return false;
4652 }
4653
4654 return true;
4655}
4656
Geoff Langff5b2d52016-09-07 11:32:23 -04004657bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4658 GLenum target,
4659 GLenum attachment,
4660 GLenum pname,
4661 GLsizei *numParams)
4662{
4663 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4664 *numParams = 1;
4665
4666 if (!ValidFramebufferTarget(target))
4667 {
4668 context->handleError(Error(GL_INVALID_ENUM));
4669 return false;
4670 }
4671
4672 int clientVersion = context->getClientMajorVersion();
4673
4674 switch (pname)
4675 {
4676 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4677 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4678 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4679 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4680 break;
4681
4682 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4683 if (clientVersion < 3 && !context->getExtensions().sRGB)
4684 {
4685 context->handleError(Error(GL_INVALID_ENUM));
4686 return false;
4687 }
4688 break;
4689
4690 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4691 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4692 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4693 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4694 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4695 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4696 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4697 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4698 if (clientVersion < 3)
4699 {
4700 context->handleError(Error(GL_INVALID_ENUM));
4701 return false;
4702 }
4703 break;
4704
4705 default:
4706 context->handleError(Error(GL_INVALID_ENUM));
4707 return false;
4708 }
4709
4710 // Determine if the attachment is a valid enum
4711 switch (attachment)
4712 {
4713 case GL_BACK:
4714 case GL_FRONT:
4715 case GL_DEPTH:
4716 case GL_STENCIL:
4717 case GL_DEPTH_STENCIL_ATTACHMENT:
4718 if (clientVersion < 3)
4719 {
4720 context->handleError(Error(GL_INVALID_ENUM));
4721 return false;
4722 }
4723 break;
4724
4725 case GL_DEPTH_ATTACHMENT:
4726 case GL_STENCIL_ATTACHMENT:
4727 break;
4728
4729 default:
4730 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4731 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4732 {
4733 context->handleError(Error(GL_INVALID_ENUM));
4734 return false;
4735 }
4736 break;
4737 }
4738
4739 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4740 ASSERT(framebuffer);
4741
4742 if (framebuffer->id() == 0)
4743 {
4744 if (clientVersion < 3)
4745 {
4746 context->handleError(Error(GL_INVALID_OPERATION));
4747 return false;
4748 }
4749
4750 switch (attachment)
4751 {
4752 case GL_BACK:
4753 case GL_DEPTH:
4754 case GL_STENCIL:
4755 break;
4756
4757 default:
4758 context->handleError(Error(GL_INVALID_OPERATION));
4759 return false;
4760 }
4761 }
4762 else
4763 {
4764 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4765 {
4766 // Valid attachment query
4767 }
4768 else
4769 {
4770 switch (attachment)
4771 {
4772 case GL_DEPTH_ATTACHMENT:
4773 case GL_STENCIL_ATTACHMENT:
4774 break;
4775
4776 case GL_DEPTH_STENCIL_ATTACHMENT:
4777 if (!framebuffer->hasValidDepthStencil())
4778 {
4779 context->handleError(Error(GL_INVALID_OPERATION));
4780 return false;
4781 }
4782 break;
4783
4784 default:
4785 context->handleError(Error(GL_INVALID_OPERATION));
4786 return false;
4787 }
4788 }
4789 }
4790
4791 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4792 if (attachmentObject)
4793 {
4794 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4795 attachmentObject->type() == GL_TEXTURE ||
4796 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4797
4798 switch (pname)
4799 {
4800 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4801 if (attachmentObject->type() != GL_RENDERBUFFER &&
4802 attachmentObject->type() != GL_TEXTURE)
4803 {
4804 context->handleError(Error(GL_INVALID_ENUM));
4805 return false;
4806 }
4807 break;
4808
4809 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4810 if (attachmentObject->type() != GL_TEXTURE)
4811 {
4812 context->handleError(Error(GL_INVALID_ENUM));
4813 return false;
4814 }
4815 break;
4816
4817 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4818 if (attachmentObject->type() != GL_TEXTURE)
4819 {
4820 context->handleError(Error(GL_INVALID_ENUM));
4821 return false;
4822 }
4823 break;
4824
4825 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4826 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4827 {
4828 context->handleError(Error(GL_INVALID_OPERATION));
4829 return false;
4830 }
4831 break;
4832
4833 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4834 if (attachmentObject->type() != GL_TEXTURE)
4835 {
4836 context->handleError(Error(GL_INVALID_ENUM));
4837 return false;
4838 }
4839 break;
4840
4841 default:
4842 break;
4843 }
4844 }
4845 else
4846 {
4847 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4848 // is NONE, then querying any other pname will generate INVALID_ENUM.
4849
4850 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4851 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4852 // INVALID_OPERATION for all other pnames
4853
4854 switch (pname)
4855 {
4856 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4857 break;
4858
4859 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4860 if (clientVersion < 3)
4861 {
4862 context->handleError(Error(GL_INVALID_ENUM));
4863 return false;
4864 }
4865 break;
4866
4867 default:
4868 if (clientVersion < 3)
4869 {
4870 context->handleError(Error(GL_INVALID_ENUM));
4871 return false;
4872 }
4873 else
4874 {
4875 context->handleError(Error(GL_INVALID_OPERATION));
4876 return false;
4877 }
4878 }
4879 }
4880
4881 return true;
4882}
4883
4884bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4885 GLenum target,
4886 GLenum attachment,
4887 GLenum pname,
4888 GLsizei bufSize,
4889 GLsizei *numParams)
4890{
4891 if (!ValidateRobustEntryPoint(context, bufSize))
4892 {
4893 return false;
4894 }
4895
4896 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4897 {
4898 return false;
4899 }
4900
4901 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4902 {
4903 return false;
4904 }
4905
4906 return true;
4907}
4908
4909bool ValidateGetBufferParameteriv(ValidationContext *context,
4910 GLenum target,
4911 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004912 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004913{
Geoff Langebebe1c2016-10-14 12:01:31 -04004914 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004915}
4916
4917bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4918 GLenum target,
4919 GLenum pname,
4920 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004921 GLsizei *length,
4922 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004923{
4924 if (!ValidateRobustEntryPoint(context, bufSize))
4925 {
4926 return false;
4927 }
4928
Geoff Langebebe1c2016-10-14 12:01:31 -04004929 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004930 {
4931 return false;
4932 }
4933
Geoff Langebebe1c2016-10-14 12:01:31 -04004934 if (!ValidateRobustBufferSize(context, bufSize, *length))
4935 {
4936 return false;
4937 }
4938
4939 return true;
4940}
4941
4942bool ValidateGetBufferParameteri64v(ValidationContext *context,
4943 GLenum target,
4944 GLenum pname,
4945 GLint64 *params)
4946{
4947 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4948}
4949
4950bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4951 GLenum target,
4952 GLenum pname,
4953 GLsizei bufSize,
4954 GLsizei *length,
4955 GLint64 *params)
4956{
4957 if (!ValidateRobustEntryPoint(context, bufSize))
4958 {
4959 return false;
4960 }
4961
4962 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4963 {
4964 return false;
4965 }
4966
4967 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004968 {
4969 return false;
4970 }
4971
4972 return true;
4973}
4974
4975bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4976{
4977 // Currently, all GetProgramiv queries return 1 parameter
4978 *numParams = 1;
4979
4980 Program *programObject = GetValidProgram(context, program);
4981 if (!programObject)
4982 {
4983 return false;
4984 }
4985
4986 switch (pname)
4987 {
4988 case GL_DELETE_STATUS:
4989 case GL_LINK_STATUS:
4990 case GL_VALIDATE_STATUS:
4991 case GL_INFO_LOG_LENGTH:
4992 case GL_ATTACHED_SHADERS:
4993 case GL_ACTIVE_ATTRIBUTES:
4994 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4995 case GL_ACTIVE_UNIFORMS:
4996 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4997 break;
4998
4999 case GL_PROGRAM_BINARY_LENGTH:
5000 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5001 {
5002 context->handleError(Error(GL_INVALID_ENUM,
5003 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5004 "GL_OES_get_program_binary or ES 3.0."));
5005 return false;
5006 }
5007 break;
5008
5009 case GL_ACTIVE_UNIFORM_BLOCKS:
5010 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5011 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5012 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5013 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5014 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5015 if (context->getClientMajorVersion() < 3)
5016 {
5017 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5018 return false;
5019 }
5020 break;
5021
5022 default:
5023 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5024 return false;
5025 }
5026
5027 return true;
5028}
5029
5030bool ValidateGetProgramivRobustANGLE(Context *context,
5031 GLuint program,
5032 GLenum pname,
5033 GLsizei bufSize,
5034 GLsizei *numParams)
5035{
5036 if (!ValidateRobustEntryPoint(context, bufSize))
5037 {
5038 return false;
5039 }
5040
5041 if (!ValidateGetProgramiv(context, program, pname, numParams))
5042 {
5043 return false;
5044 }
5045
5046 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5047 {
5048 return false;
5049 }
5050
5051 return true;
5052}
5053
Geoff Lang740d9022016-10-07 11:20:52 -04005054bool ValidateGetRenderbufferParameteriv(Context *context,
5055 GLenum target,
5056 GLenum pname,
5057 GLint *params)
5058{
5059 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5060}
5061
5062bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5063 GLenum target,
5064 GLenum pname,
5065 GLsizei bufSize,
5066 GLsizei *length,
5067 GLint *params)
5068{
5069 if (!ValidateRobustEntryPoint(context, bufSize))
5070 {
5071 return false;
5072 }
5073
5074 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5075 {
5076 return false;
5077 }
5078
5079 if (!ValidateRobustBufferSize(context, bufSize, *length))
5080 {
5081 return false;
5082 }
5083
5084 return true;
5085}
5086
Geoff Langd7d0ed32016-10-07 11:33:51 -04005087bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5088{
5089 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5090}
5091
5092bool ValidateGetShaderivRobustANGLE(Context *context,
5093 GLuint shader,
5094 GLenum pname,
5095 GLsizei bufSize,
5096 GLsizei *length,
5097 GLint *params)
5098{
5099 if (!ValidateRobustEntryPoint(context, bufSize))
5100 {
5101 return false;
5102 }
5103
5104 if (!ValidateGetShaderivBase(context, shader, pname, length))
5105 {
5106 return false;
5107 }
5108
5109 if (!ValidateRobustBufferSize(context, bufSize, *length))
5110 {
5111 return false;
5112 }
5113
5114 return true;
5115}
5116
Geoff Langc1984ed2016-10-07 12:41:00 -04005117bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5118{
5119 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5120}
5121
5122bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5123 GLenum target,
5124 GLenum pname,
5125 GLsizei bufSize,
5126 GLsizei *length,
5127 GLfloat *params)
5128{
5129 if (!ValidateRobustEntryPoint(context, bufSize))
5130 {
5131 return false;
5132 }
5133
5134 if (!ValidateGetTexParameterBase(context, target, pname, length))
5135 {
5136 return false;
5137 }
5138
5139 if (!ValidateRobustBufferSize(context, bufSize, *length))
5140 {
5141 return false;
5142 }
5143
5144 return true;
5145}
5146
5147bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5148{
5149 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5150}
5151
5152bool ValidateGetTexParameterivRobustANGLE(Context *context,
5153 GLenum target,
5154 GLenum pname,
5155 GLsizei bufSize,
5156 GLsizei *length,
5157 GLint *params)
5158{
5159 if (!ValidateRobustEntryPoint(context, bufSize))
5160 {
5161 return false;
5162 }
5163
5164 if (!ValidateGetTexParameterBase(context, target, pname, length))
5165 {
5166 return false;
5167 }
5168
5169 if (!ValidateRobustBufferSize(context, bufSize, *length))
5170 {
5171 return false;
5172 }
5173
5174 return true;
5175}
5176
5177bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5178{
5179 return ValidateTexParameterBase(context, target, pname, -1, &param);
5180}
5181
5182bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5183{
5184 return ValidateTexParameterBase(context, target, pname, -1, params);
5185}
5186
5187bool ValidateTexParameterfvRobustANGLE(Context *context,
5188 GLenum target,
5189 GLenum pname,
5190 GLsizei bufSize,
5191 const GLfloat *params)
5192{
5193 if (!ValidateRobustEntryPoint(context, bufSize))
5194 {
5195 return false;
5196 }
5197
5198 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5199}
5200
5201bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5202{
5203 return ValidateTexParameterBase(context, target, pname, -1, &param);
5204}
5205
5206bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5207{
5208 return ValidateTexParameterBase(context, target, pname, -1, params);
5209}
5210
5211bool ValidateTexParameterivRobustANGLE(Context *context,
5212 GLenum target,
5213 GLenum pname,
5214 GLsizei bufSize,
5215 const GLint *params)
5216{
5217 if (!ValidateRobustEntryPoint(context, bufSize))
5218 {
5219 return false;
5220 }
5221
5222 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5223}
5224
5225bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5226{
5227 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5228}
5229
5230bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5231 GLuint sampler,
5232 GLenum pname,
5233 GLuint bufSize,
5234 GLsizei *length,
5235 GLfloat *params)
5236{
5237 if (!ValidateRobustEntryPoint(context, bufSize))
5238 {
5239 return false;
5240 }
5241
5242 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5243 {
5244 return false;
5245 }
5246
5247 if (!ValidateRobustBufferSize(context, bufSize, *length))
5248 {
5249 return false;
5250 }
5251
5252 return true;
5253}
5254
5255bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5256{
5257 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5258}
5259
5260bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5261 GLuint sampler,
5262 GLenum pname,
5263 GLuint bufSize,
5264 GLsizei *length,
5265 GLint *params)
5266{
5267 if (!ValidateRobustEntryPoint(context, bufSize))
5268 {
5269 return false;
5270 }
5271
5272 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5273 {
5274 return false;
5275 }
5276
5277 if (!ValidateRobustBufferSize(context, bufSize, *length))
5278 {
5279 return false;
5280 }
5281
5282 return true;
5283}
5284
5285bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5286{
5287 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5288}
5289
5290bool ValidateSamplerParameterfv(Context *context,
5291 GLuint sampler,
5292 GLenum pname,
5293 const GLfloat *params)
5294{
5295 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5296}
5297
5298bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5299 GLuint sampler,
5300 GLenum pname,
5301 GLsizei bufSize,
5302 const GLfloat *params)
5303{
5304 if (!ValidateRobustEntryPoint(context, bufSize))
5305 {
5306 return false;
5307 }
5308
5309 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5310}
5311
5312bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5313{
5314 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5315}
5316
5317bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5318{
5319 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5320}
5321
5322bool ValidateSamplerParameterivRobustANGLE(Context *context,
5323 GLuint sampler,
5324 GLenum pname,
5325 GLsizei bufSize,
5326 const GLint *params)
5327{
5328 if (!ValidateRobustEntryPoint(context, bufSize))
5329 {
5330 return false;
5331 }
5332
5333 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5334}
5335
Geoff Lang0b031062016-10-13 14:30:04 -04005336bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5337{
5338 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5339}
5340
5341bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5342 GLuint index,
5343 GLenum pname,
5344 GLsizei bufSize,
5345 GLsizei *length,
5346 GLfloat *params)
5347{
5348 if (!ValidateRobustEntryPoint(context, bufSize))
5349 {
5350 return false;
5351 }
5352
5353 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5354 {
5355 return false;
5356 }
5357
5358 if (!ValidateRobustBufferSize(context, bufSize, *length))
5359 {
5360 return false;
5361 }
5362
5363 return true;
5364}
5365
5366bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5367{
5368 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5369}
5370
5371bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5372 GLuint index,
5373 GLenum pname,
5374 GLsizei bufSize,
5375 GLsizei *length,
5376 GLint *params)
5377{
5378 if (!ValidateRobustEntryPoint(context, bufSize))
5379 {
5380 return false;
5381 }
5382
5383 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5384 {
5385 return false;
5386 }
5387
5388 if (!ValidateRobustBufferSize(context, bufSize, *length))
5389 {
5390 return false;
5391 }
5392
5393 return true;
5394}
5395
5396bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5397{
5398 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5399}
5400
5401bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5402 GLuint index,
5403 GLenum pname,
5404 GLsizei bufSize,
5405 GLsizei *length,
5406 void **pointer)
5407{
5408 if (!ValidateRobustEntryPoint(context, bufSize))
5409 {
5410 return false;
5411 }
5412
5413 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5414 {
5415 return false;
5416 }
5417
5418 if (!ValidateRobustBufferSize(context, bufSize, *length))
5419 {
5420 return false;
5421 }
5422
5423 return true;
5424}
5425
5426bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5427{
5428 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5429}
5430
5431bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5432 GLuint index,
5433 GLenum pname,
5434 GLsizei bufSize,
5435 GLsizei *length,
5436 GLint *params)
5437{
5438 if (!ValidateRobustEntryPoint(context, bufSize))
5439 {
5440 return false;
5441 }
5442
5443 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5444 {
5445 return false;
5446 }
5447
5448 if (!ValidateRobustBufferSize(context, bufSize, *length))
5449 {
5450 return false;
5451 }
5452
5453 return true;
5454}
5455
5456bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5457{
5458 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5459}
5460
5461bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5462 GLuint index,
5463 GLenum pname,
5464 GLsizei bufSize,
5465 GLsizei *length,
5466 GLuint *params)
5467{
5468 if (!ValidateRobustEntryPoint(context, bufSize))
5469 {
5470 return false;
5471 }
5472
5473 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5474 {
5475 return false;
5476 }
5477
5478 if (!ValidateRobustBufferSize(context, bufSize, *length))
5479 {
5480 return false;
5481 }
5482
5483 return true;
5484}
5485
Geoff Lang6899b872016-10-14 11:30:13 -04005486bool ValidateGetActiveUniformBlockiv(Context *context,
5487 GLuint program,
5488 GLuint uniformBlockIndex,
5489 GLenum pname,
5490 GLint *params)
5491{
5492 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5493}
5494
5495bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5496 GLuint program,
5497 GLuint uniformBlockIndex,
5498 GLenum pname,
5499 GLsizei bufSize,
5500 GLsizei *length,
5501 GLint *params)
5502{
5503 if (!ValidateRobustEntryPoint(context, bufSize))
5504 {
5505 return false;
5506 }
5507
5508 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5509 {
5510 return false;
5511 }
5512
5513 if (!ValidateRobustBufferSize(context, bufSize, *length))
5514 {
5515 return false;
5516 }
5517
5518 return true;
5519}
5520
Geoff Lang0a9661f2016-10-20 10:59:20 -07005521bool ValidateGetInternalFormativ(Context *context,
5522 GLenum target,
5523 GLenum internalformat,
5524 GLenum pname,
5525 GLsizei bufSize,
5526 GLint *params)
5527{
5528 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5529 nullptr);
5530}
5531
5532bool ValidateGetInternalFormativRobustANGLE(Context *context,
5533 GLenum target,
5534 GLenum internalformat,
5535 GLenum pname,
5536 GLsizei bufSize,
5537 GLsizei *length,
5538 GLint *params)
5539{
5540 if (!ValidateRobustEntryPoint(context, bufSize))
5541 {
5542 return false;
5543 }
5544
5545 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5546 {
5547 return false;
5548 }
5549
5550 if (!ValidateRobustBufferSize(context, bufSize, *length))
5551 {
5552 return false;
5553 }
5554
5555 return true;
5556}
5557
Jamie Madillc29968b2016-01-20 11:17:23 -05005558} // namespace gl