blob: 4fc9eb756c174c2fd13a4871974fe0874a637fd2 [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 Madill51f40ec2016-06-15 14:06:00 -04003134 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003135 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3136 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003137 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003138 const FramebufferAttachment *dsAttachment =
3139 framebuffer->getStencilOrDepthStencilAttachment();
3140 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003141 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003142 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003143
3144 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3145 bool differentWritemasks =
3146 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3147 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3148 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3149 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3150
3151 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003152 {
3153 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3154 // Section 6.10 of the WebGL 1.0 spec
He Yunchaoced53ae2016-11-29 15:00:51 +08003155 ERR("This ANGLE implementation does not support separate front/back stencil "
Geoff Lang3a86ad32015-09-01 11:47:05 -04003156 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04003157 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003158 return false;
3159 }
Jamie Madillac528012014-06-20 13:21:23 -04003160 }
3161
Jamie Madill51f40ec2016-06-15 14:06:00 -04003162 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003163 {
Jamie Madill437fa652016-05-03 15:13:24 -04003164 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003165 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003166 }
3167
Geoff Lang7dd2e102014-11-10 15:19:26 -05003168 gl::Program *program = state.getProgram();
3169 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003170 {
Jamie Madill437fa652016-05-03 15:13:24 -04003171 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003172 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003173 }
3174
Geoff Lang7dd2e102014-11-10 15:19:26 -05003175 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003176 {
Jamie Madill437fa652016-05-03 15:13:24 -04003177 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003178 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003179 }
3180
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003181 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003182 for (unsigned int uniformBlockIndex = 0;
3183 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003184 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003185 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003186 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003187 const OffsetBindingPointer<Buffer> &uniformBuffer =
3188 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003189
Geoff Lang5d124a62015-09-15 13:03:27 -04003190 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003191 {
3192 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003193 context->handleError(
3194 Error(GL_INVALID_OPERATION,
3195 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003196 return false;
3197 }
3198
Geoff Lang5d124a62015-09-15 13:03:27 -04003199 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003200 if (uniformBufferSize == 0)
3201 {
3202 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003203 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003204 }
3205
Jamie Madill62d31cb2015-09-11 13:25:51 -04003206 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003207 {
3208 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003209 context->handleError(
3210 Error(GL_INVALID_OPERATION,
3211 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003212 return false;
3213 }
3214 }
3215
Jamie Madill250d33f2014-06-06 17:09:03 -04003216 // No-op if zero count
3217 return (count > 0);
3218}
3219
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003220bool ValidateDrawArrays(ValidationContext *context,
3221 GLenum mode,
3222 GLint first,
3223 GLsizei count,
3224 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003225{
Jamie Madillfd716582014-06-06 17:09:04 -04003226 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003227 {
Jamie Madill437fa652016-05-03 15:13:24 -04003228 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003229 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003230 }
3231
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003232 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003233 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003234 if (curTransformFeedback && curTransformFeedback->isActive() &&
3235 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003236 {
3237 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003238 // that does not match the current transform feedback object's draw mode (if transform
3239 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003240 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003241 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003242 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003243 }
3244
Jiajia Qind9671222016-11-29 16:30:31 +08003245 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003246 {
3247 return false;
3248 }
3249
Corentin Wallez71168a02016-12-19 15:11:18 -08003250 // Check the computation of maxVertex doesn't overflow.
3251 // - first < 0 or count < 0 have been checked as an error condition
3252 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3253 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3254 ASSERT(count > 0 && first >= 0);
3255 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3256 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003257 {
3258 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3259 return false;
3260 }
3261
Corentin Wallez71168a02016-12-19 15:11:18 -08003262 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003263 {
3264 return false;
3265 }
3266
3267 return true;
3268}
3269
He Yunchaoced53ae2016-11-29 15:00:51 +08003270bool ValidateDrawArraysInstanced(Context *context,
3271 GLenum mode,
3272 GLint first,
3273 GLsizei count,
3274 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003275{
3276 if (primcount < 0)
3277 {
Jamie Madill437fa652016-05-03 15:13:24 -04003278 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003279 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003280 }
3281
Jamie Madill2b976812014-08-25 15:47:49 -04003282 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003283 {
3284 return false;
3285 }
3286
3287 // No-op if zero primitive count
3288 return (primcount > 0);
3289}
3290
Geoff Lang87a93302014-09-16 13:29:43 -04003291static bool ValidateDrawInstancedANGLE(Context *context)
3292{
3293 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003294 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003295
Geoff Lang7dd2e102014-11-10 15:19:26 -05003296 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003297
3298 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003299 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003300 {
3301 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003302 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003303 {
3304 return true;
3305 }
3306 }
3307
Jamie Madill437fa652016-05-03 15:13:24 -04003308 context->handleError(Error(GL_INVALID_OPERATION,
3309 "ANGLE_instanced_arrays requires that at least one active attribute"
3310 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003311 return false;
3312}
3313
He Yunchaoced53ae2016-11-29 15:00:51 +08003314bool ValidateDrawArraysInstancedANGLE(Context *context,
3315 GLenum mode,
3316 GLint first,
3317 GLsizei count,
3318 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003319{
3320 if (!ValidateDrawInstancedANGLE(context))
3321 {
3322 return false;
3323 }
3324
3325 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3326}
3327
Jiajia Qind9671222016-11-29 16:30:31 +08003328bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003329{
Jamie Madill250d33f2014-06-06 17:09:03 -04003330 switch (type)
3331 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003332 case GL_UNSIGNED_BYTE:
3333 case GL_UNSIGNED_SHORT:
3334 break;
3335 case GL_UNSIGNED_INT:
3336 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3337 {
3338 context->handleError(Error(GL_INVALID_ENUM));
3339 return false;
3340 }
3341 break;
3342 default:
3343 context->handleError(Error(GL_INVALID_ENUM));
3344 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003345 }
3346
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003347 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003348
3349 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003350 if (curTransformFeedback && curTransformFeedback->isActive() &&
3351 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003352 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003353 // It is an invalid operation to call DrawElements, DrawRangeElements or
3354 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003355 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003356 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003357 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003358 }
3359
Jiajia Qind9671222016-11-29 16:30:31 +08003360 return true;
3361}
3362
3363bool ValidateDrawElements(ValidationContext *context,
3364 GLenum mode,
3365 GLsizei count,
3366 GLenum type,
3367 const GLvoid *indices,
3368 GLsizei primcount,
3369 IndexRange *indexRangeOut)
3370{
3371 if (!ValidateDrawElementsBase(context, type))
3372 return false;
3373
3374 const State &state = context->getGLState();
3375
Jamie Madill250d33f2014-06-06 17:09:03 -04003376 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003377 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003378 {
Jamie Madill437fa652016-05-03 15:13:24 -04003379 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003380 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003381 }
3382
He Yunchaoced53ae2016-11-29 15:00:51 +08003383 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003384 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003385
Jamie Madillae3000b2014-08-25 15:47:51 -04003386 if (elementArrayBuffer)
3387 {
3388 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3389
3390 GLint64 offset = reinterpret_cast<GLint64>(indices);
He Yunchaoced53ae2016-11-29 15:00:51 +08003391 GLint64 byteCount =
3392 static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count) + offset;
Jamie Madillae3000b2014-08-25 15:47:51 -04003393
3394 // check for integer overflows
3395 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3396 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3397 {
Jamie Madill437fa652016-05-03 15:13:24 -04003398 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003399 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003400 }
3401
3402 // Check for reading past the end of the bound buffer object
3403 if (byteCount > elementArrayBuffer->getSize())
3404 {
Jamie Madill437fa652016-05-03 15:13:24 -04003405 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003406 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003407 }
3408 }
Corentin Wallez327411e2016-12-09 11:09:17 -05003409 else if (context->getExtensions().webglCompatibility && count > 0)
3410 {
3411 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3412 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3413 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3414 context->handleError(
3415 Error(GL_INVALID_OPERATION, "There is no element array buffer bound and count > 0."));
3416 return false;
3417 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003418 else if (!indices)
3419 {
Corentin Wallez327411e2016-12-09 11:09:17 -05003420 // This is an application error that would normally result in a crash,
3421 // but we catch it and return an error
3422 context->handleError(
3423 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003424 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003425 }
3426
Jiajia Qind9671222016-11-29 16:30:31 +08003427 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003428 {
3429 return false;
3430 }
3431
Jamie Madill2b976812014-08-25 15:47:49 -04003432 // Use max index to validate if our vertex buffers are large enough for the pull.
3433 // TODO: offer fast path, with disabled index validation.
3434 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3435 if (elementArrayBuffer)
3436 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003437 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003438 Error error =
3439 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3440 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003441 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003442 {
Jamie Madill437fa652016-05-03 15:13:24 -04003443 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003444 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003445 }
3446 }
3447 else
3448 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003449 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003450 }
3451
Jamie Madille79b1e12015-11-04 16:36:37 -05003452 // If we use an index greater than our maximum supported index range, return an error.
3453 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3454 // return an error if possible here.
3455 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3456 {
Jamie Madill437fa652016-05-03 15:13:24 -04003457 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003458 return false;
3459 }
3460
Corentin Wallez92db6942016-12-09 13:10:36 -05003461 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3462 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003463 {
3464 return false;
3465 }
3466
Geoff Lang3edfe032015-09-04 16:38:24 -04003467 // No op if there are no real indices in the index data (all are primitive restart).
3468 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003469}
3470
Geoff Langb1196682014-07-23 13:47:29 -04003471bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003472 GLenum mode,
3473 GLsizei count,
3474 GLenum type,
3475 const GLvoid *indices,
3476 GLsizei primcount,
3477 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003478{
3479 if (primcount < 0)
3480 {
Jamie Madill437fa652016-05-03 15:13:24 -04003481 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003482 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003483 }
3484
Jamie Madill2b976812014-08-25 15:47:49 -04003485 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003486 {
3487 return false;
3488 }
3489
3490 // No-op zero primitive count
3491 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003492}
3493
Geoff Lang3edfe032015-09-04 16:38:24 -04003494bool ValidateDrawElementsInstancedANGLE(Context *context,
3495 GLenum mode,
3496 GLsizei count,
3497 GLenum type,
3498 const GLvoid *indices,
3499 GLsizei primcount,
3500 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003501{
3502 if (!ValidateDrawInstancedANGLE(context))
3503 {
3504 return false;
3505 }
3506
He Yunchaoced53ae2016-11-29 15:00:51 +08003507 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3508 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003509}
3510
He Yunchaoced53ae2016-11-29 15:00:51 +08003511bool ValidateFramebufferTextureBase(Context *context,
3512 GLenum target,
3513 GLenum attachment,
3514 GLuint texture,
3515 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003516{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003517 if (!ValidFramebufferTarget(target))
3518 {
Jamie Madill437fa652016-05-03 15:13:24 -04003519 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003520 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003521 }
3522
3523 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003524 {
3525 return false;
3526 }
3527
Jamie Madill55ec3b12014-07-03 10:38:57 -04003528 if (texture != 0)
3529 {
3530 gl::Texture *tex = context->getTexture(texture);
3531
3532 if (tex == NULL)
3533 {
Jamie Madill437fa652016-05-03 15:13:24 -04003534 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003535 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003536 }
3537
3538 if (level < 0)
3539 {
Jamie Madill437fa652016-05-03 15:13:24 -04003540 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003541 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003542 }
3543 }
3544
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003545 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003546 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003547
Jamie Madill84115c92015-04-23 15:00:07 -04003548 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003549 {
Jamie Madill437fa652016-05-03 15:13:24 -04003550 context->handleError(
3551 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003552 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003553 }
3554
3555 return true;
3556}
3557
He Yunchaoced53ae2016-11-29 15:00:51 +08003558bool ValidateFramebufferTexture2D(Context *context,
3559 GLenum target,
3560 GLenum attachment,
3561 GLenum textarget,
3562 GLuint texture,
3563 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003564{
He Yunchaoced53ae2016-11-29 15:00:51 +08003565 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3566 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003567 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3568 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003569 {
Jamie Madill437fa652016-05-03 15:13:24 -04003570 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003571 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003572 }
3573
3574 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003575 {
3576 return false;
3577 }
3578
Jamie Madill55ec3b12014-07-03 10:38:57 -04003579 if (texture != 0)
3580 {
3581 gl::Texture *tex = context->getTexture(texture);
3582 ASSERT(tex);
3583
Jamie Madill2a6564e2014-07-11 09:53:19 -04003584 const gl::Caps &caps = context->getCaps();
3585
Jamie Madill55ec3b12014-07-03 10:38:57 -04003586 switch (textarget)
3587 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003588 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003589 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003590 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003591 {
Jamie Madill437fa652016-05-03 15:13:24 -04003592 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003593 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003594 }
3595 if (tex->getTarget() != GL_TEXTURE_2D)
3596 {
Jamie Madill437fa652016-05-03 15:13:24 -04003597 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003598 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003599 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003600 }
3601 break;
3602
He Yunchaoced53ae2016-11-29 15:00:51 +08003603 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3604 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3605 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3606 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3607 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3608 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003609 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003610 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003611 {
Jamie Madill437fa652016-05-03 15:13:24 -04003612 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003613 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003614 }
3615 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3616 {
Jamie Madill437fa652016-05-03 15:13:24 -04003617 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003618 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003619 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003620 }
3621 break;
3622
He Yunchaoced53ae2016-11-29 15:00:51 +08003623 default:
3624 context->handleError(Error(GL_INVALID_ENUM));
3625 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003626 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003627
Jamie Madilla3944d42016-07-22 22:13:26 -04003628 const Format &format = tex->getFormat(textarget, level);
3629 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003630 {
Jamie Madill437fa652016-05-03 15:13:24 -04003631 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003632 return false;
3633 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003634 }
3635
Jamie Madill570f7c82014-07-03 10:38:54 -04003636 return true;
3637}
3638
Geoff Langb1196682014-07-23 13:47:29 -04003639bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003640{
3641 if (program == 0)
3642 {
Jamie Madill437fa652016-05-03 15:13:24 -04003643 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003644 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003645 }
3646
Dian Xiang769769a2015-09-09 15:20:08 -07003647 gl::Program *programObject = GetValidProgram(context, program);
3648 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003649 {
3650 return false;
3651 }
3652
Jamie Madill0063c512014-08-25 15:47:53 -04003653 if (!programObject || !programObject->isLinked())
3654 {
Jamie Madill437fa652016-05-03 15:13:24 -04003655 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003656 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003657 }
3658
Geoff Lang7dd2e102014-11-10 15:19:26 -05003659 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003660 {
Jamie Madill437fa652016-05-03 15:13:24 -04003661 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003662 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003663 }
3664
Jamie Madill0063c512014-08-25 15:47:53 -04003665 return true;
3666}
3667
He Yunchaoced53ae2016-11-29 15:00:51 +08003668bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003669{
3670 return ValidateGetUniformBase(context, program, location);
3671}
3672
He Yunchaoced53ae2016-11-29 15:00:51 +08003673bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003674{
Jamie Madill78f41802014-08-25 15:47:55 -04003675 return ValidateGetUniformBase(context, program, location);
3676}
3677
Geoff Langf41d0ee2016-10-07 13:04:23 -04003678static bool ValidateSizedGetUniform(Context *context,
3679 GLuint program,
3680 GLint location,
3681 GLsizei bufSize,
3682 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003683{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003684 if (length)
3685 {
3686 *length = 0;
3687 }
3688
Jamie Madill78f41802014-08-25 15:47:55 -04003689 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003690 {
Jamie Madill78f41802014-08-25 15:47:55 -04003691 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003692 }
3693
Geoff Langf41d0ee2016-10-07 13:04:23 -04003694 if (bufSize < 0)
3695 {
3696 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3697 return false;
3698 }
3699
Jamie Madilla502c742014-08-28 17:19:13 -04003700 gl::Program *programObject = context->getProgram(program);
3701 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003702
Jamie Madill78f41802014-08-25 15:47:55 -04003703 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003704 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003705 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003706 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003707 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003708 context->handleError(
3709 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003710 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003711 }
3712
Geoff Langf41d0ee2016-10-07 13:04:23 -04003713 if (length)
3714 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003715 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003716 }
3717
Jamie Madill0063c512014-08-25 15:47:53 -04003718 return true;
3719}
3720
He Yunchaoced53ae2016-11-29 15:00:51 +08003721bool ValidateGetnUniformfvEXT(Context *context,
3722 GLuint program,
3723 GLint location,
3724 GLsizei bufSize,
3725 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003726{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003727 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003728}
3729
He Yunchaoced53ae2016-11-29 15:00:51 +08003730bool ValidateGetnUniformivEXT(Context *context,
3731 GLuint program,
3732 GLint location,
3733 GLsizei bufSize,
3734 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003735{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003736 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3737}
3738
3739bool ValidateGetUniformfvRobustANGLE(Context *context,
3740 GLuint program,
3741 GLint location,
3742 GLsizei bufSize,
3743 GLsizei *length,
3744 GLfloat *params)
3745{
3746 if (!ValidateRobustEntryPoint(context, bufSize))
3747 {
3748 return false;
3749 }
3750
3751 // bufSize is validated in ValidateSizedGetUniform
3752 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3753}
3754
3755bool ValidateGetUniformivRobustANGLE(Context *context,
3756 GLuint program,
3757 GLint location,
3758 GLsizei bufSize,
3759 GLsizei *length,
3760 GLint *params)
3761{
3762 if (!ValidateRobustEntryPoint(context, bufSize))
3763 {
3764 return false;
3765 }
3766
3767 // bufSize is validated in ValidateSizedGetUniform
3768 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3769}
3770
3771bool ValidateGetUniformuivRobustANGLE(Context *context,
3772 GLuint program,
3773 GLint location,
3774 GLsizei bufSize,
3775 GLsizei *length,
3776 GLuint *params)
3777{
3778 if (!ValidateRobustEntryPoint(context, bufSize))
3779 {
3780 return false;
3781 }
3782
3783 if (context->getClientMajorVersion() < 3)
3784 {
3785 context->handleError(
3786 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3787 return false;
3788 }
3789
3790 // bufSize is validated in ValidateSizedGetUniform
3791 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003792}
3793
He Yunchaoced53ae2016-11-29 15:00:51 +08003794bool ValidateDiscardFramebufferBase(Context *context,
3795 GLenum target,
3796 GLsizei numAttachments,
3797 const GLenum *attachments,
3798 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003799{
3800 if (numAttachments < 0)
3801 {
Jamie Madill437fa652016-05-03 15:13:24 -04003802 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003803 return false;
3804 }
3805
3806 for (GLsizei i = 0; i < numAttachments; ++i)
3807 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003808 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003809 {
3810 if (defaultFramebuffer)
3811 {
Jamie Madill437fa652016-05-03 15:13:24 -04003812 context->handleError(Error(
3813 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003814 return false;
3815 }
3816
3817 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3818 {
Jamie Madill437fa652016-05-03 15:13:24 -04003819 context->handleError(Error(GL_INVALID_OPERATION,
3820 "Requested color attachment is greater than the maximum "
3821 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003822 return false;
3823 }
3824 }
3825 else
3826 {
3827 switch (attachments[i])
3828 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003829 case GL_DEPTH_ATTACHMENT:
3830 case GL_STENCIL_ATTACHMENT:
3831 case GL_DEPTH_STENCIL_ATTACHMENT:
3832 if (defaultFramebuffer)
3833 {
3834 context->handleError(
3835 Error(GL_INVALID_ENUM,
3836 "Invalid attachment when the default framebuffer is bound"));
3837 return false;
3838 }
3839 break;
3840 case GL_COLOR:
3841 case GL_DEPTH:
3842 case GL_STENCIL:
3843 if (!defaultFramebuffer)
3844 {
3845 context->handleError(
3846 Error(GL_INVALID_ENUM,
3847 "Invalid attachment when the default framebuffer is not bound"));
3848 return false;
3849 }
3850 break;
3851 default:
3852 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003853 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003854 }
3855 }
3856 }
3857
3858 return true;
3859}
3860
Austin Kinross6ee1e782015-05-29 17:05:37 -07003861bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3862{
3863 // Note that debug marker calls must not set error state
3864
3865 if (length < 0)
3866 {
3867 return false;
3868 }
3869
3870 if (marker == nullptr)
3871 {
3872 return false;
3873 }
3874
3875 return true;
3876}
3877
3878bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3879{
3880 // Note that debug marker calls must not set error state
3881
3882 if (length < 0)
3883 {
3884 return false;
3885 }
3886
3887 if (length > 0 && marker == nullptr)
3888 {
3889 return false;
3890 }
3891
3892 return true;
3893}
3894
Geoff Langdcab33b2015-07-21 13:03:16 -04003895bool ValidateEGLImageTargetTexture2DOES(Context *context,
3896 egl::Display *display,
3897 GLenum target,
3898 egl::Image *image)
3899{
Geoff Langa8406172015-07-21 16:53:39 -04003900 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3901 {
Jamie Madill437fa652016-05-03 15:13:24 -04003902 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003903 return false;
3904 }
3905
3906 switch (target)
3907 {
3908 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003909 if (!context->getExtensions().eglImage)
3910 {
3911 context->handleError(Error(
3912 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3913 }
3914 break;
3915
3916 case GL_TEXTURE_EXTERNAL_OES:
3917 if (!context->getExtensions().eglImageExternal)
3918 {
3919 context->handleError(Error(
3920 GL_INVALID_ENUM,
3921 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3922 }
Geoff Langa8406172015-07-21 16:53:39 -04003923 break;
3924
3925 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003926 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003927 return false;
3928 }
3929
3930 if (!display->isValidImage(image))
3931 {
Jamie Madill437fa652016-05-03 15:13:24 -04003932 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003933 return false;
3934 }
3935
3936 if (image->getSamples() > 0)
3937 {
Jamie Madill437fa652016-05-03 15:13:24 -04003938 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003939 "cannot create a 2D texture from a multisampled EGL image."));
3940 return false;
3941 }
3942
Jamie Madilla3944d42016-07-22 22:13:26 -04003943 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003944 if (!textureCaps.texturable)
3945 {
Jamie Madill437fa652016-05-03 15:13:24 -04003946 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003947 "EGL image internal format is not supported as a texture."));
3948 return false;
3949 }
3950
Geoff Langdcab33b2015-07-21 13:03:16 -04003951 return true;
3952}
3953
3954bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3955 egl::Display *display,
3956 GLenum target,
3957 egl::Image *image)
3958{
Geoff Langa8406172015-07-21 16:53:39 -04003959 if (!context->getExtensions().eglImage)
3960 {
Jamie Madill437fa652016-05-03 15:13:24 -04003961 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003962 return false;
3963 }
3964
3965 switch (target)
3966 {
3967 case GL_RENDERBUFFER:
3968 break;
3969
3970 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003971 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003972 return false;
3973 }
3974
3975 if (!display->isValidImage(image))
3976 {
Jamie Madill437fa652016-05-03 15:13:24 -04003977 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003978 return false;
3979 }
3980
Jamie Madilla3944d42016-07-22 22:13:26 -04003981 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003982 if (!textureCaps.renderable)
3983 {
Jamie Madill437fa652016-05-03 15:13:24 -04003984 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003985 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3986 return false;
3987 }
3988
Geoff Langdcab33b2015-07-21 13:03:16 -04003989 return true;
3990}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003991
3992bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3993{
Geoff Lang36167ab2015-12-07 10:27:14 -05003994 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003995 {
3996 // The default VAO should always exist
3997 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003998 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003999 return false;
4000 }
4001
4002 return true;
4003}
4004
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004005bool ValidateLinkProgram(Context *context, GLuint program)
4006{
4007 if (context->hasActiveTransformFeedback(program))
4008 {
4009 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004010 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004011 "Cannot link program while program is associated with an active "
4012 "transform feedback object."));
4013 return false;
4014 }
4015 return true;
4016}
4017
Geoff Langc5629752015-12-07 16:29:04 -05004018bool ValidateProgramBinaryBase(Context *context,
4019 GLuint program,
4020 GLenum binaryFormat,
4021 const void *binary,
4022 GLint length)
4023{
4024 Program *programObject = GetValidProgram(context, program);
4025 if (programObject == nullptr)
4026 {
4027 return false;
4028 }
4029
4030 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4031 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4032 programBinaryFormats.end())
4033 {
Jamie Madill437fa652016-05-03 15:13:24 -04004034 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004035 return false;
4036 }
4037
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004038 if (context->hasActiveTransformFeedback(program))
4039 {
4040 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004041 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004042 "Cannot change program binary while program is associated with "
4043 "an active transform feedback object."));
4044 return false;
4045 }
4046
Geoff Langc5629752015-12-07 16:29:04 -05004047 return true;
4048}
4049
4050bool ValidateGetProgramBinaryBase(Context *context,
4051 GLuint program,
4052 GLsizei bufSize,
4053 GLsizei *length,
4054 GLenum *binaryFormat,
4055 void *binary)
4056{
4057 Program *programObject = GetValidProgram(context, program);
4058 if (programObject == nullptr)
4059 {
4060 return false;
4061 }
4062
4063 if (!programObject->isLinked())
4064 {
Jamie Madill437fa652016-05-03 15:13:24 -04004065 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004066 return false;
4067 }
4068
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004069 if (context->getCaps().programBinaryFormats.empty())
4070 {
4071 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4072 return false;
4073 }
4074
Geoff Langc5629752015-12-07 16:29:04 -05004075 return true;
4076}
Jamie Madillc29968b2016-01-20 11:17:23 -05004077
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004078bool ValidateUseProgram(Context *context, GLuint program)
4079{
4080 if (program != 0)
4081 {
4082 Program *programObject = context->getProgram(program);
4083 if (!programObject)
4084 {
4085 // ES 3.1.0 section 7.3 page 72
4086 if (context->getShader(program))
4087 {
Jamie Madill437fa652016-05-03 15:13:24 -04004088 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004089 Error(GL_INVALID_OPERATION,
4090 "Attempted to use a single shader instead of a shader program."));
4091 return false;
4092 }
4093 else
4094 {
Jamie Madill437fa652016-05-03 15:13:24 -04004095 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004096 return false;
4097 }
4098 }
4099 if (!programObject->isLinked())
4100 {
Jamie Madill437fa652016-05-03 15:13:24 -04004101 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004102 return false;
4103 }
4104 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004105 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004106 {
4107 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004108 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004109 Error(GL_INVALID_OPERATION,
4110 "Cannot change active program while transform feedback is unpaused."));
4111 return false;
4112 }
4113
4114 return true;
4115}
4116
Jamie Madillc29968b2016-01-20 11:17:23 -05004117bool ValidateCopyTexImage2D(ValidationContext *context,
4118 GLenum target,
4119 GLint level,
4120 GLenum internalformat,
4121 GLint x,
4122 GLint y,
4123 GLsizei width,
4124 GLsizei height,
4125 GLint border)
4126{
Martin Radev1be913c2016-07-11 17:59:16 +03004127 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004128 {
4129 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4130 0, x, y, width, height, border);
4131 }
4132
Martin Radev1be913c2016-07-11 17:59:16 +03004133 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004134 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4135 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004136}
Jamie Madillc29968b2016-01-20 11:17:23 -05004137
4138bool ValidateFramebufferRenderbuffer(Context *context,
4139 GLenum target,
4140 GLenum attachment,
4141 GLenum renderbuffertarget,
4142 GLuint renderbuffer)
4143{
4144 if (!ValidFramebufferTarget(target) ||
4145 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4146 {
Jamie Madill437fa652016-05-03 15:13:24 -04004147 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004148 return false;
4149 }
4150
4151 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4152 renderbuffertarget, renderbuffer);
4153}
4154
4155bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4156{
4157 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4158 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4159 {
Jamie Madill437fa652016-05-03 15:13:24 -04004160 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004161 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4162 return false;
4163 }
4164
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004165 ASSERT(context->getGLState().getDrawFramebuffer());
4166 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004167 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4168
4169 // This should come first before the check for the default frame buffer
4170 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4171 // rather than INVALID_OPERATION
4172 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4173 {
4174 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4175
4176 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004177 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4178 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004179 {
4180 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004181 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4182 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4183 // 3.1 is still a bit ambiguous about the error, but future specs are
4184 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004185 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004186 return false;
4187 }
4188 else if (bufs[colorAttachment] >= maxColorAttachment)
4189 {
Jamie Madill437fa652016-05-03 15:13:24 -04004190 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004191 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004192 return false;
4193 }
4194 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4195 frameBufferId != 0)
4196 {
4197 // INVALID_OPERATION-GL is bound to buffer and ith argument
4198 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004199 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004200 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4201 return false;
4202 }
4203 }
4204
4205 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4206 // and n is not 1 or bufs is bound to value other than BACK and NONE
4207 if (frameBufferId == 0)
4208 {
4209 if (n != 1)
4210 {
Jamie Madill437fa652016-05-03 15:13:24 -04004211 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004212 "n must be 1 when GL is bound to the default framebuffer"));
4213 return false;
4214 }
4215
4216 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4217 {
Jamie Madill437fa652016-05-03 15:13:24 -04004218 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004219 GL_INVALID_OPERATION,
4220 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4221 return false;
4222 }
4223 }
4224
4225 return true;
4226}
4227
4228bool ValidateCopyTexSubImage2D(Context *context,
4229 GLenum target,
4230 GLint level,
4231 GLint xoffset,
4232 GLint yoffset,
4233 GLint x,
4234 GLint y,
4235 GLsizei width,
4236 GLsizei height)
4237{
Martin Radev1be913c2016-07-11 17:59:16 +03004238 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004239 {
4240 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4241 yoffset, x, y, width, height, 0);
4242 }
4243
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004244 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4245 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004246}
4247
Geoff Lang496c02d2016-10-20 11:38:11 -07004248bool ValidateGetBufferPointervBase(Context *context,
4249 GLenum target,
4250 GLenum pname,
4251 GLsizei *length,
4252 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004253{
Geoff Lang496c02d2016-10-20 11:38:11 -07004254 if (length)
4255 {
4256 *length = 0;
4257 }
4258
4259 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4260 {
4261 context->handleError(
4262 Error(GL_INVALID_OPERATION,
4263 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
4264 return false;
4265 }
4266
Olli Etuaho4f667482016-03-30 15:56:35 +03004267 if (!ValidBufferTarget(context, target))
4268 {
Jamie Madill437fa652016-05-03 15:13:24 -04004269 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004270 return false;
4271 }
4272
Geoff Lang496c02d2016-10-20 11:38:11 -07004273 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004274 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004275 case GL_BUFFER_MAP_POINTER:
4276 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004277
Geoff Lang496c02d2016-10-20 11:38:11 -07004278 default:
4279 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4280 return false;
4281 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004282
4283 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4284 // target bound to zero generate an INVALID_OPERATION error."
4285 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004286 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004287 {
Jamie Madill437fa652016-05-03 15:13:24 -04004288 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004289 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4290 return false;
4291 }
4292
Geoff Lang496c02d2016-10-20 11:38:11 -07004293 if (length)
4294 {
4295 *length = 1;
4296 }
4297
Olli Etuaho4f667482016-03-30 15:56:35 +03004298 return true;
4299}
4300
4301bool ValidateUnmapBufferBase(Context *context, GLenum target)
4302{
4303 if (!ValidBufferTarget(context, target))
4304 {
Jamie Madill437fa652016-05-03 15:13:24 -04004305 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004306 return false;
4307 }
4308
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004309 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004310
4311 if (buffer == nullptr || !buffer->isMapped())
4312 {
Jamie Madill437fa652016-05-03 15:13:24 -04004313 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004314 return false;
4315 }
4316
4317 return true;
4318}
4319
4320bool ValidateMapBufferRangeBase(Context *context,
4321 GLenum target,
4322 GLintptr offset,
4323 GLsizeiptr length,
4324 GLbitfield access)
4325{
4326 if (!ValidBufferTarget(context, target))
4327 {
Jamie Madill437fa652016-05-03 15:13:24 -04004328 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004329 return false;
4330 }
4331
4332 if (offset < 0 || length < 0)
4333 {
Jamie Madill437fa652016-05-03 15:13:24 -04004334 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004335 return false;
4336 }
4337
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004338 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004339
4340 if (!buffer)
4341 {
Jamie Madill437fa652016-05-03 15:13:24 -04004342 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004343 return false;
4344 }
4345
4346 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004347 CheckedNumeric<size_t> checkedOffset(offset);
4348 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004349
Jamie Madille2e406c2016-06-02 13:04:10 -04004350 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004351 {
Jamie Madill437fa652016-05-03 15:13:24 -04004352 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004353 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4354 return false;
4355 }
4356
4357 // Check for invalid bits in the mask
4358 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4359 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4360 GL_MAP_UNSYNCHRONIZED_BIT;
4361
4362 if (access & ~(allAccessBits))
4363 {
Jamie Madill437fa652016-05-03 15:13:24 -04004364 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004365 return false;
4366 }
4367
4368 if (length == 0)
4369 {
Jamie Madill437fa652016-05-03 15:13:24 -04004370 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004371 return false;
4372 }
4373
4374 if (buffer->isMapped())
4375 {
Jamie Madill437fa652016-05-03 15:13:24 -04004376 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004377 return false;
4378 }
4379
4380 // Check for invalid bit combinations
4381 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4382 {
Jamie Madill437fa652016-05-03 15:13:24 -04004383 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004384 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4385 return false;
4386 }
4387
4388 GLbitfield writeOnlyBits =
4389 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4390
4391 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4392 {
Jamie Madill437fa652016-05-03 15:13:24 -04004393 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004394 "Invalid access bits when mapping buffer for reading: 0x%X.",
4395 access));
4396 return false;
4397 }
4398
4399 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4400 {
Jamie Madill437fa652016-05-03 15:13:24 -04004401 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004402 GL_INVALID_OPERATION,
4403 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4404 return false;
4405 }
4406 return true;
4407}
4408
4409bool ValidateFlushMappedBufferRangeBase(Context *context,
4410 GLenum target,
4411 GLintptr offset,
4412 GLsizeiptr length)
4413{
4414 if (offset < 0 || length < 0)
4415 {
Jamie Madill437fa652016-05-03 15:13:24 -04004416 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004417 return false;
4418 }
4419
4420 if (!ValidBufferTarget(context, target))
4421 {
Jamie Madill437fa652016-05-03 15:13:24 -04004422 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004423 return false;
4424 }
4425
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004426 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004427
4428 if (buffer == nullptr)
4429 {
Jamie Madill437fa652016-05-03 15:13:24 -04004430 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004431 return false;
4432 }
4433
4434 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4435 {
Jamie Madill437fa652016-05-03 15:13:24 -04004436 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004437 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4438 return false;
4439 }
4440
4441 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004442 CheckedNumeric<size_t> checkedOffset(offset);
4443 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004444
Jamie Madille2e406c2016-06-02 13:04:10 -04004445 if (!checkedSize.IsValid() ||
4446 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004447 {
Jamie Madill437fa652016-05-03 15:13:24 -04004448 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004449 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4450 return false;
4451 }
4452
4453 return true;
4454}
4455
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004456bool ValidateGenerateMipmap(Context *context, GLenum target)
4457{
4458 if (!ValidTextureTarget(context, target))
4459 {
4460 context->handleError(Error(GL_INVALID_ENUM));
4461 return false;
4462 }
4463
4464 Texture *texture = context->getTargetTexture(target);
4465
4466 if (texture == nullptr)
4467 {
4468 context->handleError(Error(GL_INVALID_OPERATION));
4469 return false;
4470 }
4471
4472 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4473
4474 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4475 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4476 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4477 {
4478 context->handleError(Error(GL_INVALID_OPERATION));
4479 return false;
4480 }
4481
Jamie Madilla3944d42016-07-22 22:13:26 -04004482 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4483 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4484 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004485
4486 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4487 // unsized formats or that are color renderable and filterable. Since we do not track if
4488 // the texture was created with sized or unsized format (only sized formats are stored),
4489 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4490 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4491 // textures since they're the only texture format that can be created with unsized formats
4492 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4493 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004494 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4495 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004496 {
4497 context->handleError(Error(GL_INVALID_OPERATION));
4498 return false;
4499 }
4500
4501 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004502 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004503 {
4504 context->handleError(Error(GL_INVALID_OPERATION));
4505 return false;
4506 }
4507
4508 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004509 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004510 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4511 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4512 {
Geoff Lang55482a12016-11-21 16:54:01 -05004513 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004514 context->handleError(Error(GL_INVALID_OPERATION));
4515 return false;
4516 }
4517
4518 // Cube completeness check
4519 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4520 {
4521 context->handleError(Error(GL_INVALID_OPERATION));
4522 return false;
4523 }
4524
4525 return true;
4526}
4527
Olli Etuaho41997e72016-03-10 13:38:39 +02004528bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4529{
4530 return ValidateGenOrDelete(context, n);
4531}
4532
4533bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4534{
4535 return ValidateGenOrDelete(context, n);
4536}
4537
4538bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4539{
4540 return ValidateGenOrDelete(context, n);
4541}
4542
4543bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4544{
4545 return ValidateGenOrDelete(context, n);
4546}
4547
4548bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4549{
4550 return ValidateGenOrDelete(context, n);
4551}
4552
4553bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4554{
4555 return ValidateGenOrDelete(context, n);
4556}
4557
4558bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4559{
4560 return ValidateGenOrDelete(context, n);
4561}
4562
4563bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4564{
4565 return ValidateGenOrDelete(context, n);
4566}
4567
4568bool ValidateGenOrDelete(Context *context, GLint n)
4569{
4570 if (n < 0)
4571 {
Jamie Madill437fa652016-05-03 15:13:24 -04004572 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004573 return false;
4574 }
4575 return true;
4576}
4577
Geoff Langf41a7152016-09-19 15:11:17 -04004578bool ValidateEnable(Context *context, GLenum cap)
4579{
4580 if (!ValidCap(context, cap, false))
4581 {
4582 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4583 return false;
4584 }
4585
4586 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4587 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4588 {
4589 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4590 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4591
4592 // We also output an error message to the debugger window if tracing is active, so that
4593 // developers can see the error message.
4594 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004595 return false;
4596 }
4597
4598 return true;
4599}
4600
4601bool ValidateDisable(Context *context, GLenum cap)
4602{
4603 if (!ValidCap(context, cap, false))
4604 {
4605 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4606 return false;
4607 }
4608
4609 return true;
4610}
4611
4612bool ValidateIsEnabled(Context *context, GLenum cap)
4613{
4614 if (!ValidCap(context, cap, true))
4615 {
4616 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4617 return false;
4618 }
4619
4620 return true;
4621}
4622
Geoff Langff5b2d52016-09-07 11:32:23 -04004623bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4624{
4625 if (!context->getExtensions().robustClientMemory)
4626 {
4627 context->handleError(
4628 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4629 return false;
4630 }
4631
4632 if (bufSize < 0)
4633 {
4634 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4635 return false;
4636 }
4637
4638 return true;
4639}
4640
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004641bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4642{
4643 if (bufSize < numParams)
4644 {
4645 context->handleError(Error(GL_INVALID_OPERATION,
4646 "%u parameters are required but %i were provided.", numParams,
4647 bufSize));
4648 return false;
4649 }
4650
4651 return true;
4652}
4653
Geoff Langff5b2d52016-09-07 11:32:23 -04004654bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4655 GLenum target,
4656 GLenum attachment,
4657 GLenum pname,
4658 GLsizei *numParams)
4659{
4660 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4661 *numParams = 1;
4662
4663 if (!ValidFramebufferTarget(target))
4664 {
4665 context->handleError(Error(GL_INVALID_ENUM));
4666 return false;
4667 }
4668
4669 int clientVersion = context->getClientMajorVersion();
4670
4671 switch (pname)
4672 {
4673 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4674 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4675 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4676 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4677 break;
4678
4679 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4680 if (clientVersion < 3 && !context->getExtensions().sRGB)
4681 {
4682 context->handleError(Error(GL_INVALID_ENUM));
4683 return false;
4684 }
4685 break;
4686
4687 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4688 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4689 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4690 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4691 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4692 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4693 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4694 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4695 if (clientVersion < 3)
4696 {
4697 context->handleError(Error(GL_INVALID_ENUM));
4698 return false;
4699 }
4700 break;
4701
4702 default:
4703 context->handleError(Error(GL_INVALID_ENUM));
4704 return false;
4705 }
4706
4707 // Determine if the attachment is a valid enum
4708 switch (attachment)
4709 {
4710 case GL_BACK:
4711 case GL_FRONT:
4712 case GL_DEPTH:
4713 case GL_STENCIL:
4714 case GL_DEPTH_STENCIL_ATTACHMENT:
4715 if (clientVersion < 3)
4716 {
4717 context->handleError(Error(GL_INVALID_ENUM));
4718 return false;
4719 }
4720 break;
4721
4722 case GL_DEPTH_ATTACHMENT:
4723 case GL_STENCIL_ATTACHMENT:
4724 break;
4725
4726 default:
4727 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4728 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4729 {
4730 context->handleError(Error(GL_INVALID_ENUM));
4731 return false;
4732 }
4733 break;
4734 }
4735
4736 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4737 ASSERT(framebuffer);
4738
4739 if (framebuffer->id() == 0)
4740 {
4741 if (clientVersion < 3)
4742 {
4743 context->handleError(Error(GL_INVALID_OPERATION));
4744 return false;
4745 }
4746
4747 switch (attachment)
4748 {
4749 case GL_BACK:
4750 case GL_DEPTH:
4751 case GL_STENCIL:
4752 break;
4753
4754 default:
4755 context->handleError(Error(GL_INVALID_OPERATION));
4756 return false;
4757 }
4758 }
4759 else
4760 {
4761 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4762 {
4763 // Valid attachment query
4764 }
4765 else
4766 {
4767 switch (attachment)
4768 {
4769 case GL_DEPTH_ATTACHMENT:
4770 case GL_STENCIL_ATTACHMENT:
4771 break;
4772
4773 case GL_DEPTH_STENCIL_ATTACHMENT:
4774 if (!framebuffer->hasValidDepthStencil())
4775 {
4776 context->handleError(Error(GL_INVALID_OPERATION));
4777 return false;
4778 }
4779 break;
4780
4781 default:
4782 context->handleError(Error(GL_INVALID_OPERATION));
4783 return false;
4784 }
4785 }
4786 }
4787
4788 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4789 if (attachmentObject)
4790 {
4791 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4792 attachmentObject->type() == GL_TEXTURE ||
4793 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4794
4795 switch (pname)
4796 {
4797 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4798 if (attachmentObject->type() != GL_RENDERBUFFER &&
4799 attachmentObject->type() != GL_TEXTURE)
4800 {
4801 context->handleError(Error(GL_INVALID_ENUM));
4802 return false;
4803 }
4804 break;
4805
4806 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4807 if (attachmentObject->type() != GL_TEXTURE)
4808 {
4809 context->handleError(Error(GL_INVALID_ENUM));
4810 return false;
4811 }
4812 break;
4813
4814 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4815 if (attachmentObject->type() != GL_TEXTURE)
4816 {
4817 context->handleError(Error(GL_INVALID_ENUM));
4818 return false;
4819 }
4820 break;
4821
4822 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4823 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4824 {
4825 context->handleError(Error(GL_INVALID_OPERATION));
4826 return false;
4827 }
4828 break;
4829
4830 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4831 if (attachmentObject->type() != GL_TEXTURE)
4832 {
4833 context->handleError(Error(GL_INVALID_ENUM));
4834 return false;
4835 }
4836 break;
4837
4838 default:
4839 break;
4840 }
4841 }
4842 else
4843 {
4844 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4845 // is NONE, then querying any other pname will generate INVALID_ENUM.
4846
4847 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4848 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4849 // INVALID_OPERATION for all other pnames
4850
4851 switch (pname)
4852 {
4853 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4854 break;
4855
4856 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4857 if (clientVersion < 3)
4858 {
4859 context->handleError(Error(GL_INVALID_ENUM));
4860 return false;
4861 }
4862 break;
4863
4864 default:
4865 if (clientVersion < 3)
4866 {
4867 context->handleError(Error(GL_INVALID_ENUM));
4868 return false;
4869 }
4870 else
4871 {
4872 context->handleError(Error(GL_INVALID_OPERATION));
4873 return false;
4874 }
4875 }
4876 }
4877
4878 return true;
4879}
4880
4881bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4882 GLenum target,
4883 GLenum attachment,
4884 GLenum pname,
4885 GLsizei bufSize,
4886 GLsizei *numParams)
4887{
4888 if (!ValidateRobustEntryPoint(context, bufSize))
4889 {
4890 return false;
4891 }
4892
4893 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4894 {
4895 return false;
4896 }
4897
4898 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4899 {
4900 return false;
4901 }
4902
4903 return true;
4904}
4905
4906bool ValidateGetBufferParameteriv(ValidationContext *context,
4907 GLenum target,
4908 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004909 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004910{
Geoff Langebebe1c2016-10-14 12:01:31 -04004911 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004912}
4913
4914bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4915 GLenum target,
4916 GLenum pname,
4917 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004918 GLsizei *length,
4919 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004920{
4921 if (!ValidateRobustEntryPoint(context, bufSize))
4922 {
4923 return false;
4924 }
4925
Geoff Langebebe1c2016-10-14 12:01:31 -04004926 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004927 {
4928 return false;
4929 }
4930
Geoff Langebebe1c2016-10-14 12:01:31 -04004931 if (!ValidateRobustBufferSize(context, bufSize, *length))
4932 {
4933 return false;
4934 }
4935
4936 return true;
4937}
4938
4939bool ValidateGetBufferParameteri64v(ValidationContext *context,
4940 GLenum target,
4941 GLenum pname,
4942 GLint64 *params)
4943{
4944 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4945}
4946
4947bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4948 GLenum target,
4949 GLenum pname,
4950 GLsizei bufSize,
4951 GLsizei *length,
4952 GLint64 *params)
4953{
4954 if (!ValidateRobustEntryPoint(context, bufSize))
4955 {
4956 return false;
4957 }
4958
4959 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4960 {
4961 return false;
4962 }
4963
4964 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004965 {
4966 return false;
4967 }
4968
4969 return true;
4970}
4971
4972bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4973{
4974 // Currently, all GetProgramiv queries return 1 parameter
4975 *numParams = 1;
4976
4977 Program *programObject = GetValidProgram(context, program);
4978 if (!programObject)
4979 {
4980 return false;
4981 }
4982
4983 switch (pname)
4984 {
4985 case GL_DELETE_STATUS:
4986 case GL_LINK_STATUS:
4987 case GL_VALIDATE_STATUS:
4988 case GL_INFO_LOG_LENGTH:
4989 case GL_ATTACHED_SHADERS:
4990 case GL_ACTIVE_ATTRIBUTES:
4991 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4992 case GL_ACTIVE_UNIFORMS:
4993 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4994 break;
4995
4996 case GL_PROGRAM_BINARY_LENGTH:
4997 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4998 {
4999 context->handleError(Error(GL_INVALID_ENUM,
5000 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5001 "GL_OES_get_program_binary or ES 3.0."));
5002 return false;
5003 }
5004 break;
5005
5006 case GL_ACTIVE_UNIFORM_BLOCKS:
5007 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5008 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5009 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5010 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5011 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5012 if (context->getClientMajorVersion() < 3)
5013 {
5014 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5015 return false;
5016 }
5017 break;
5018
5019 default:
5020 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5021 return false;
5022 }
5023
5024 return true;
5025}
5026
5027bool ValidateGetProgramivRobustANGLE(Context *context,
5028 GLuint program,
5029 GLenum pname,
5030 GLsizei bufSize,
5031 GLsizei *numParams)
5032{
5033 if (!ValidateRobustEntryPoint(context, bufSize))
5034 {
5035 return false;
5036 }
5037
5038 if (!ValidateGetProgramiv(context, program, pname, numParams))
5039 {
5040 return false;
5041 }
5042
5043 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5044 {
5045 return false;
5046 }
5047
5048 return true;
5049}
5050
Geoff Lang740d9022016-10-07 11:20:52 -04005051bool ValidateGetRenderbufferParameteriv(Context *context,
5052 GLenum target,
5053 GLenum pname,
5054 GLint *params)
5055{
5056 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5057}
5058
5059bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5060 GLenum target,
5061 GLenum pname,
5062 GLsizei bufSize,
5063 GLsizei *length,
5064 GLint *params)
5065{
5066 if (!ValidateRobustEntryPoint(context, bufSize))
5067 {
5068 return false;
5069 }
5070
5071 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5072 {
5073 return false;
5074 }
5075
5076 if (!ValidateRobustBufferSize(context, bufSize, *length))
5077 {
5078 return false;
5079 }
5080
5081 return true;
5082}
5083
Geoff Langd7d0ed32016-10-07 11:33:51 -04005084bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5085{
5086 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5087}
5088
5089bool ValidateGetShaderivRobustANGLE(Context *context,
5090 GLuint shader,
5091 GLenum pname,
5092 GLsizei bufSize,
5093 GLsizei *length,
5094 GLint *params)
5095{
5096 if (!ValidateRobustEntryPoint(context, bufSize))
5097 {
5098 return false;
5099 }
5100
5101 if (!ValidateGetShaderivBase(context, shader, pname, length))
5102 {
5103 return false;
5104 }
5105
5106 if (!ValidateRobustBufferSize(context, bufSize, *length))
5107 {
5108 return false;
5109 }
5110
5111 return true;
5112}
5113
Geoff Langc1984ed2016-10-07 12:41:00 -04005114bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5115{
5116 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5117}
5118
5119bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5120 GLenum target,
5121 GLenum pname,
5122 GLsizei bufSize,
5123 GLsizei *length,
5124 GLfloat *params)
5125{
5126 if (!ValidateRobustEntryPoint(context, bufSize))
5127 {
5128 return false;
5129 }
5130
5131 if (!ValidateGetTexParameterBase(context, target, pname, length))
5132 {
5133 return false;
5134 }
5135
5136 if (!ValidateRobustBufferSize(context, bufSize, *length))
5137 {
5138 return false;
5139 }
5140
5141 return true;
5142}
5143
5144bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5145{
5146 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5147}
5148
5149bool ValidateGetTexParameterivRobustANGLE(Context *context,
5150 GLenum target,
5151 GLenum pname,
5152 GLsizei bufSize,
5153 GLsizei *length,
5154 GLint *params)
5155{
5156 if (!ValidateRobustEntryPoint(context, bufSize))
5157 {
5158 return false;
5159 }
5160
5161 if (!ValidateGetTexParameterBase(context, target, pname, length))
5162 {
5163 return false;
5164 }
5165
5166 if (!ValidateRobustBufferSize(context, bufSize, *length))
5167 {
5168 return false;
5169 }
5170
5171 return true;
5172}
5173
5174bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5175{
5176 return ValidateTexParameterBase(context, target, pname, -1, &param);
5177}
5178
5179bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5180{
5181 return ValidateTexParameterBase(context, target, pname, -1, params);
5182}
5183
5184bool ValidateTexParameterfvRobustANGLE(Context *context,
5185 GLenum target,
5186 GLenum pname,
5187 GLsizei bufSize,
5188 const GLfloat *params)
5189{
5190 if (!ValidateRobustEntryPoint(context, bufSize))
5191 {
5192 return false;
5193 }
5194
5195 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5196}
5197
5198bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5199{
5200 return ValidateTexParameterBase(context, target, pname, -1, &param);
5201}
5202
5203bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5204{
5205 return ValidateTexParameterBase(context, target, pname, -1, params);
5206}
5207
5208bool ValidateTexParameterivRobustANGLE(Context *context,
5209 GLenum target,
5210 GLenum pname,
5211 GLsizei bufSize,
5212 const GLint *params)
5213{
5214 if (!ValidateRobustEntryPoint(context, bufSize))
5215 {
5216 return false;
5217 }
5218
5219 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5220}
5221
5222bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5223{
5224 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5225}
5226
5227bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5228 GLuint sampler,
5229 GLenum pname,
5230 GLuint bufSize,
5231 GLsizei *length,
5232 GLfloat *params)
5233{
5234 if (!ValidateRobustEntryPoint(context, bufSize))
5235 {
5236 return false;
5237 }
5238
5239 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5240 {
5241 return false;
5242 }
5243
5244 if (!ValidateRobustBufferSize(context, bufSize, *length))
5245 {
5246 return false;
5247 }
5248
5249 return true;
5250}
5251
5252bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5253{
5254 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5255}
5256
5257bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5258 GLuint sampler,
5259 GLenum pname,
5260 GLuint bufSize,
5261 GLsizei *length,
5262 GLint *params)
5263{
5264 if (!ValidateRobustEntryPoint(context, bufSize))
5265 {
5266 return false;
5267 }
5268
5269 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5270 {
5271 return false;
5272 }
5273
5274 if (!ValidateRobustBufferSize(context, bufSize, *length))
5275 {
5276 return false;
5277 }
5278
5279 return true;
5280}
5281
5282bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5283{
5284 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5285}
5286
5287bool ValidateSamplerParameterfv(Context *context,
5288 GLuint sampler,
5289 GLenum pname,
5290 const GLfloat *params)
5291{
5292 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5293}
5294
5295bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5296 GLuint sampler,
5297 GLenum pname,
5298 GLsizei bufSize,
5299 const GLfloat *params)
5300{
5301 if (!ValidateRobustEntryPoint(context, bufSize))
5302 {
5303 return false;
5304 }
5305
5306 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5307}
5308
5309bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5310{
5311 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5312}
5313
5314bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5315{
5316 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5317}
5318
5319bool ValidateSamplerParameterivRobustANGLE(Context *context,
5320 GLuint sampler,
5321 GLenum pname,
5322 GLsizei bufSize,
5323 const GLint *params)
5324{
5325 if (!ValidateRobustEntryPoint(context, bufSize))
5326 {
5327 return false;
5328 }
5329
5330 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5331}
5332
Geoff Lang0b031062016-10-13 14:30:04 -04005333bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5334{
5335 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5336}
5337
5338bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5339 GLuint index,
5340 GLenum pname,
5341 GLsizei bufSize,
5342 GLsizei *length,
5343 GLfloat *params)
5344{
5345 if (!ValidateRobustEntryPoint(context, bufSize))
5346 {
5347 return false;
5348 }
5349
5350 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5351 {
5352 return false;
5353 }
5354
5355 if (!ValidateRobustBufferSize(context, bufSize, *length))
5356 {
5357 return false;
5358 }
5359
5360 return true;
5361}
5362
5363bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5364{
5365 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5366}
5367
5368bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5369 GLuint index,
5370 GLenum pname,
5371 GLsizei bufSize,
5372 GLsizei *length,
5373 GLint *params)
5374{
5375 if (!ValidateRobustEntryPoint(context, bufSize))
5376 {
5377 return false;
5378 }
5379
5380 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5381 {
5382 return false;
5383 }
5384
5385 if (!ValidateRobustBufferSize(context, bufSize, *length))
5386 {
5387 return false;
5388 }
5389
5390 return true;
5391}
5392
5393bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5394{
5395 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5396}
5397
5398bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5399 GLuint index,
5400 GLenum pname,
5401 GLsizei bufSize,
5402 GLsizei *length,
5403 void **pointer)
5404{
5405 if (!ValidateRobustEntryPoint(context, bufSize))
5406 {
5407 return false;
5408 }
5409
5410 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5411 {
5412 return false;
5413 }
5414
5415 if (!ValidateRobustBufferSize(context, bufSize, *length))
5416 {
5417 return false;
5418 }
5419
5420 return true;
5421}
5422
5423bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5424{
5425 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5426}
5427
5428bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5429 GLuint index,
5430 GLenum pname,
5431 GLsizei bufSize,
5432 GLsizei *length,
5433 GLint *params)
5434{
5435 if (!ValidateRobustEntryPoint(context, bufSize))
5436 {
5437 return false;
5438 }
5439
5440 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5441 {
5442 return false;
5443 }
5444
5445 if (!ValidateRobustBufferSize(context, bufSize, *length))
5446 {
5447 return false;
5448 }
5449
5450 return true;
5451}
5452
5453bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5454{
5455 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5456}
5457
5458bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5459 GLuint index,
5460 GLenum pname,
5461 GLsizei bufSize,
5462 GLsizei *length,
5463 GLuint *params)
5464{
5465 if (!ValidateRobustEntryPoint(context, bufSize))
5466 {
5467 return false;
5468 }
5469
5470 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5471 {
5472 return false;
5473 }
5474
5475 if (!ValidateRobustBufferSize(context, bufSize, *length))
5476 {
5477 return false;
5478 }
5479
5480 return true;
5481}
5482
Geoff Lang6899b872016-10-14 11:30:13 -04005483bool ValidateGetActiveUniformBlockiv(Context *context,
5484 GLuint program,
5485 GLuint uniformBlockIndex,
5486 GLenum pname,
5487 GLint *params)
5488{
5489 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5490}
5491
5492bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5493 GLuint program,
5494 GLuint uniformBlockIndex,
5495 GLenum pname,
5496 GLsizei bufSize,
5497 GLsizei *length,
5498 GLint *params)
5499{
5500 if (!ValidateRobustEntryPoint(context, bufSize))
5501 {
5502 return false;
5503 }
5504
5505 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5506 {
5507 return false;
5508 }
5509
5510 if (!ValidateRobustBufferSize(context, bufSize, *length))
5511 {
5512 return false;
5513 }
5514
5515 return true;
5516}
5517
Geoff Lang0a9661f2016-10-20 10:59:20 -07005518bool ValidateGetInternalFormativ(Context *context,
5519 GLenum target,
5520 GLenum internalformat,
5521 GLenum pname,
5522 GLsizei bufSize,
5523 GLint *params)
5524{
5525 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5526 nullptr);
5527}
5528
5529bool ValidateGetInternalFormativRobustANGLE(Context *context,
5530 GLenum target,
5531 GLenum internalformat,
5532 GLenum pname,
5533 GLsizei bufSize,
5534 GLsizei *length,
5535 GLint *params)
5536{
5537 if (!ValidateRobustEntryPoint(context, bufSize))
5538 {
5539 return false;
5540 }
5541
5542 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5543 {
5544 return false;
5545 }
5546
5547 if (!ValidateRobustBufferSize(context, bufSize, *length))
5548 {
5549 return false;
5550 }
5551
5552 return true;
5553}
5554
Jamie Madillc29968b2016-01-20 11:17:23 -05005555} // namespace gl