blob: 43fa7ef00126d945cc8a3479b7654de0e1f55d00 [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];
Corentin Wallezfd456442016-12-21 17:57:00 -050053 if (!program->isAttribLocationActive(attributeIndex) || !attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040054 {
Corentin Wallezfd456442016-12-21 17:57:00 -050055 continue;
56 }
Jamie Madill1ca74672015-07-21 15:14:11 -040057
Corentin Wallezfd456442016-12-21 17:57:00 -050058 // If we have no buffer, then we either get an error, or there are no more checks to be done.
59 gl::Buffer *buffer = attrib.buffer.get();
60 if (!buffer)
61 {
62 if (webglCompatibility)
Corentin Wallez327411e2016-12-09 11:09:17 -050063 {
64 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050065 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
66 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
67 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
68 // error.
Corentin Wallez327411e2016-12-09 11:09:17 -050069 context->handleError(
70 Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer."));
Corentin Wallezfd456442016-12-21 17:57:00 -050071 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050072 }
Corentin Wallezfd456442016-12-21 17:57:00 -050073 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040074 {
75 // This is an application error that would normally result in a crash,
76 // but we catch it and return an error
Corentin Wallezfd456442016-12-21 17:57:00 -050077 context->handleError(
78 Error(GL_INVALID_OPERATION,
79 "An enabled vertex array has no buffer and no pointer."));
Jamie Madill1ca74672015-07-21 15:14:11 -040080 return false;
81 }
Corentin Wallezfd456442016-12-21 17:57:00 -050082 continue;
83 }
84
85 // If we're drawing zero vertices, we have enough data.
86 if (vertexCount <= 0 || primcount <= 0)
87 {
88 continue;
89 }
90
91 GLint maxVertexElement = 0;
92 if (attrib.divisor == 0)
93 {
94 maxVertexElement = maxVertex;
95 }
96 else
97 {
98 maxVertexElement = (primcount - 1) / attrib.divisor;
99 }
100
101 // We do manual overflow checks here instead of using safe_math.h because it was
102 // a bottleneck. Thanks to some properties of GL we know inequalities that can
103 // help us make the overflow checks faster.
104
105 // The max possible attribSize is 16 for a vector of 4 32 bit values.
106 constexpr uint64_t kMaxAttribSize = 16;
107 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
108 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
109
110 // We know attribStride is given as a GLsizei which is typedefed to int.
111 // We also know an upper bound for attribSize.
112 static_assert(std::is_same<int, GLsizei>::value, "");
113 uint64_t attribStride = ComputeVertexAttributeStride(attrib);
114 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
115 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
116
117 // Computing the max offset using uint64_t without attrib.offset is overflow
118 // safe. Note: Last vertex element does not take the full stride!
119 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
120 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
121
122 // An overflow can happen when adding the offset, check for it.
123 uint64_t attribOffset = attrib.offset;
124 if (attribDataSizeNoOffset > kUint64Max - attrib.offset)
125 {
126 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
127 return false;
128 }
129 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
130
131 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
132 // We can return INVALID_OPERATION if our vertex attribute does not have
133 // enough backing data.
134 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
135 {
136 context->handleError(Error(GL_INVALID_OPERATION,
137 "Vertex buffer is not big enough for the draw call"));
138 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400139 }
140 }
141
142 return true;
143}
144
Geoff Langf607c602016-09-21 11:46:48 -0400145bool ValidReadPixelsFormatType(ValidationContext *context,
146 GLenum framebufferComponentType,
147 GLenum format,
148 GLenum type)
149{
150 switch (framebufferComponentType)
151 {
152 case GL_UNSIGNED_NORMALIZED:
153 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
154 // ReadPixels with BGRA even if the extension is not present
155 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
156 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
157 type == GL_UNSIGNED_BYTE);
158
159 case GL_SIGNED_NORMALIZED:
160 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
161
162 case GL_INT:
163 return (format == GL_RGBA_INTEGER && type == GL_INT);
164
165 case GL_UNSIGNED_INT:
166 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
167
168 case GL_FLOAT:
169 return (format == GL_RGBA && type == GL_FLOAT);
170
171 default:
172 UNREACHABLE();
173 return false;
174 }
175}
176
Geoff Langf41a7152016-09-19 15:11:17 -0400177bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500178{
179 switch (cap)
180 {
Geoff Langf41a7152016-09-19 15:11:17 -0400181 // EXT_multisample_compatibility
182 case GL_MULTISAMPLE_EXT:
183 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
184 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300185
Geoff Langf41a7152016-09-19 15:11:17 -0400186 case GL_CULL_FACE:
187 case GL_POLYGON_OFFSET_FILL:
188 case GL_SAMPLE_ALPHA_TO_COVERAGE:
189 case GL_SAMPLE_COVERAGE:
190 case GL_SCISSOR_TEST:
191 case GL_STENCIL_TEST:
192 case GL_DEPTH_TEST:
193 case GL_BLEND:
194 case GL_DITHER:
195 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500196
Geoff Langf41a7152016-09-19 15:11:17 -0400197 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
198 case GL_RASTERIZER_DISCARD:
199 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500200
Geoff Langf41a7152016-09-19 15:11:17 -0400201 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
202 case GL_DEBUG_OUTPUT:
203 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500204
Geoff Langf41a7152016-09-19 15:11:17 -0400205 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
206 return queryOnly && context->getExtensions().bindGeneratesResource;
207
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700208 case GL_FRAMEBUFFER_SRGB_EXT:
209 return context->getExtensions().sRGBWriteControl;
210
Geoff Lang3b573612016-10-31 14:08:10 -0400211 case GL_SAMPLE_MASK:
Geoff Lang3b573612016-10-31 14:08:10 -0400212 return context->getClientVersion() >= Version(3, 1);
213
Geoff Langf41a7152016-09-19 15:11:17 -0400214 default:
215 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500216 }
217}
218
Geoff Lang62fce5b2016-09-30 10:46:35 -0400219bool ValidateReadPixelsBase(ValidationContext *context,
220 GLint x,
221 GLint y,
222 GLsizei width,
223 GLsizei height,
224 GLenum format,
225 GLenum type,
226 GLsizei bufSize,
227 GLsizei *length,
228 GLvoid *pixels)
229{
230 if (length != nullptr)
231 {
232 *length = 0;
233 }
234
235 if (width < 0 || height < 0)
236 {
237 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
238 return false;
239 }
240
241 auto readFramebuffer = context->getGLState().getReadFramebuffer();
242
243 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
244 {
245 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
246 return false;
247 }
248
249 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
250 {
251 context->handleError(Error(GL_INVALID_OPERATION));
252 return false;
253 }
254
255 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
256 ASSERT(framebuffer);
257
258 if (framebuffer->getReadBufferState() == GL_NONE)
259 {
260 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
261 return false;
262 }
263
264 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500265 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
266 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
267 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
268 // situation is an application error that would lead to a crash in ANGLE.
269 if (readBuffer == nullptr)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400270 {
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500271 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
Geoff Lang62fce5b2016-09-30 10:46:35 -0400272 return false;
273 }
274
275 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
276 GLenum currentType = framebuffer->getImplementationColorReadType();
277 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
278
279 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
280 bool validFormatTypeCombination =
281 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
282
283 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
284 {
285 context->handleError(Error(GL_INVALID_OPERATION));
286 return false;
287 }
288
289 // Check for pixel pack buffer related API errors
290 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
291 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
292 {
293 // ...the buffer object's data store is currently mapped.
294 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
295 return false;
296 }
297
298 // .. the data would be packed to the buffer object such that the memory writes required
299 // would exceed the data store size.
300 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
301 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
302 const gl::Extents size(width, height, 1);
303 const auto &pack = context->getGLState().getPackState();
304
305 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
306 if (endByteOrErr.isError())
307 {
308 context->handleError(endByteOrErr.getError());
309 return false;
310 }
311
312 size_t endByte = endByteOrErr.getResult();
313 if (bufSize >= 0)
314 {
315
316 if (static_cast<size_t>(bufSize) < endByte)
317 {
318 context->handleError(
319 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
320 return false;
321 }
322 }
323
324 if (pixelPackBuffer != nullptr)
325 {
326 CheckedNumeric<size_t> checkedEndByte(endByte);
327 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
328 checkedEndByte += checkedOffset;
329
330 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
331 {
332 // Overflow past the end of the buffer
333 context->handleError(
334 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
335 return false;
336 }
337 }
338
339 if (length != nullptr)
340 {
341 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
342 {
343 context->handleError(
344 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
345 return false;
346 }
347
348 *length = static_cast<GLsizei>(endByte);
349 }
350
351 return true;
352}
353
Geoff Lang740d9022016-10-07 11:20:52 -0400354bool ValidateGetRenderbufferParameterivBase(Context *context,
355 GLenum target,
356 GLenum pname,
357 GLsizei *length)
358{
359 if (length)
360 {
361 *length = 0;
362 }
363
364 if (target != GL_RENDERBUFFER)
365 {
366 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
367 return false;
368 }
369
370 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
371 if (renderbuffer == nullptr)
372 {
373 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
374 return false;
375 }
376
377 switch (pname)
378 {
379 case GL_RENDERBUFFER_WIDTH:
380 case GL_RENDERBUFFER_HEIGHT:
381 case GL_RENDERBUFFER_INTERNAL_FORMAT:
382 case GL_RENDERBUFFER_RED_SIZE:
383 case GL_RENDERBUFFER_GREEN_SIZE:
384 case GL_RENDERBUFFER_BLUE_SIZE:
385 case GL_RENDERBUFFER_ALPHA_SIZE:
386 case GL_RENDERBUFFER_DEPTH_SIZE:
387 case GL_RENDERBUFFER_STENCIL_SIZE:
388 break;
389
390 case GL_RENDERBUFFER_SAMPLES_ANGLE:
391 if (!context->getExtensions().framebufferMultisample)
392 {
393 context->handleError(
394 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
395 return false;
396 }
397 break;
398
399 default:
400 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
401 return false;
402 }
403
404 if (length)
405 {
406 *length = 1;
407 }
408 return true;
409}
410
Geoff Langd7d0ed32016-10-07 11:33:51 -0400411bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
412{
413 if (length)
414 {
415 *length = 0;
416 }
417
418 if (GetValidShader(context, shader) == nullptr)
419 {
420 return false;
421 }
422
423 switch (pname)
424 {
425 case GL_SHADER_TYPE:
426 case GL_DELETE_STATUS:
427 case GL_COMPILE_STATUS:
428 case GL_INFO_LOG_LENGTH:
429 case GL_SHADER_SOURCE_LENGTH:
430 break;
431
432 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
433 if (!context->getExtensions().translatedShaderSource)
434 {
435 context->handleError(
436 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
437 return false;
438 }
439 break;
440
441 default:
442 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
443 return false;
444 }
445
446 if (length)
447 {
448 *length = 1;
449 }
450 return true;
451}
452
Geoff Langc1984ed2016-10-07 12:41:00 -0400453bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
454{
455 if (length)
456 {
457 *length = 0;
458 }
459
460 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
461 {
462 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
463 return false;
464 }
465
466 if (context->getTargetTexture(target) == nullptr)
467 {
468 // Should only be possible for external textures
469 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
470 return false;
471 }
472
473 switch (pname)
474 {
475 case GL_TEXTURE_MAG_FILTER:
476 case GL_TEXTURE_MIN_FILTER:
477 case GL_TEXTURE_WRAP_S:
478 case GL_TEXTURE_WRAP_T:
479 break;
480
481 case GL_TEXTURE_USAGE_ANGLE:
482 if (!context->getExtensions().textureUsage)
483 {
484 context->handleError(
485 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
486 return false;
487 }
488 break;
489
490 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
491 if (!context->getExtensions().textureFilterAnisotropic)
492 {
493 context->handleError(
494 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
495 return false;
496 }
497 break;
498
499 case GL_TEXTURE_IMMUTABLE_FORMAT:
500 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
501 {
502 context->handleError(
503 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
504 return false;
505 }
506 break;
507
508 case GL_TEXTURE_WRAP_R:
509 case GL_TEXTURE_IMMUTABLE_LEVELS:
510 case GL_TEXTURE_SWIZZLE_R:
511 case GL_TEXTURE_SWIZZLE_G:
512 case GL_TEXTURE_SWIZZLE_B:
513 case GL_TEXTURE_SWIZZLE_A:
514 case GL_TEXTURE_BASE_LEVEL:
515 case GL_TEXTURE_MAX_LEVEL:
516 case GL_TEXTURE_MIN_LOD:
517 case GL_TEXTURE_MAX_LOD:
518 case GL_TEXTURE_COMPARE_MODE:
519 case GL_TEXTURE_COMPARE_FUNC:
520 if (context->getClientMajorVersion() < 3)
521 {
522 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
523 return false;
524 }
525 break;
526
Geoff Lang81c6b572016-10-19 14:07:52 -0700527 case GL_TEXTURE_SRGB_DECODE_EXT:
528 if (!context->getExtensions().textureSRGBDecode)
529 {
530 context->handleError(
531 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
532 return false;
533 }
534 break;
535
Geoff Langc1984ed2016-10-07 12:41:00 -0400536 default:
537 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
538 return false;
539 }
540
541 if (length)
542 {
543 *length = 1;
544 }
545 return true;
546}
547
548template <typename ParamType>
549bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
550{
551 switch (ConvertToGLenum(params[0]))
552 {
553 case GL_CLAMP_TO_EDGE:
554 break;
555
556 case GL_REPEAT:
557 case GL_MIRRORED_REPEAT:
558 if (isExternalTextureTarget)
559 {
560 // OES_EGL_image_external specifies this error.
561 context->handleError(Error(
562 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
563 return false;
564 }
565 break;
566
567 default:
568 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
569 return false;
570 }
571
572 return true;
573}
574
575template <typename ParamType>
576bool ValidateTextureMinFilterValue(Context *context,
577 ParamType *params,
578 bool isExternalTextureTarget)
579{
580 switch (ConvertToGLenum(params[0]))
581 {
582 case GL_NEAREST:
583 case GL_LINEAR:
584 break;
585
586 case GL_NEAREST_MIPMAP_NEAREST:
587 case GL_LINEAR_MIPMAP_NEAREST:
588 case GL_NEAREST_MIPMAP_LINEAR:
589 case GL_LINEAR_MIPMAP_LINEAR:
590 if (isExternalTextureTarget)
591 {
592 // OES_EGL_image_external specifies this error.
593 context->handleError(
594 Error(GL_INVALID_ENUM,
595 "external textures only support NEAREST and LINEAR filtering"));
596 return false;
597 }
598 break;
599
600 default:
601 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
602 return false;
603 }
604
605 return true;
606}
607
608template <typename ParamType>
609bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
610{
611 switch (ConvertToGLenum(params[0]))
612 {
613 case GL_NEAREST:
614 case GL_LINEAR:
615 break;
616
617 default:
618 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
619 return false;
620 }
621
622 return true;
623}
624
625template <typename ParamType>
626bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
627{
628 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
629 switch (ConvertToGLenum(params[0]))
630 {
631 case GL_NONE:
632 case GL_COMPARE_REF_TO_TEXTURE:
633 break;
634
635 default:
636 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
637 return false;
638 }
639
640 return true;
641}
642
643template <typename ParamType>
644bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
645{
646 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
647 switch (ConvertToGLenum(params[0]))
648 {
649 case GL_LEQUAL:
650 case GL_GEQUAL:
651 case GL_LESS:
652 case GL_GREATER:
653 case GL_EQUAL:
654 case GL_NOTEQUAL:
655 case GL_ALWAYS:
656 case GL_NEVER:
657 break;
658
659 default:
660 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
661 return false;
662 }
663
664 return true;
665}
666
667template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700668bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
669{
670 if (!context->getExtensions().textureSRGBDecode)
671 {
672 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
673 return false;
674 }
675
676 switch (ConvertToGLenum(params[0]))
677 {
678 case GL_DECODE_EXT:
679 case GL_SKIP_DECODE_EXT:
680 break;
681
682 default:
683 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
684 return false;
685 }
686
687 return true;
688}
689
690template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400691bool ValidateTexParameterBase(Context *context,
692 GLenum target,
693 GLenum pname,
694 GLsizei bufSize,
695 ParamType *params)
696{
697 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
698 {
699 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
700 return false;
701 }
702
703 if (context->getTargetTexture(target) == nullptr)
704 {
705 // Should only be possible for external textures
706 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
707 return false;
708 }
709
710 const GLsizei minBufSize = 1;
711 if (bufSize >= 0 && bufSize < minBufSize)
712 {
713 context->handleError(
714 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
715 return false;
716 }
717
718 switch (pname)
719 {
720 case GL_TEXTURE_WRAP_R:
721 case GL_TEXTURE_SWIZZLE_R:
722 case GL_TEXTURE_SWIZZLE_G:
723 case GL_TEXTURE_SWIZZLE_B:
724 case GL_TEXTURE_SWIZZLE_A:
725 case GL_TEXTURE_BASE_LEVEL:
726 case GL_TEXTURE_MAX_LEVEL:
727 case GL_TEXTURE_COMPARE_MODE:
728 case GL_TEXTURE_COMPARE_FUNC:
729 case GL_TEXTURE_MIN_LOD:
730 case GL_TEXTURE_MAX_LOD:
731 if (context->getClientMajorVersion() < 3)
732 {
733 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
734 return false;
735 }
736 if (target == GL_TEXTURE_EXTERNAL_OES &&
737 !context->getExtensions().eglImageExternalEssl3)
738 {
739 context->handleError(Error(GL_INVALID_ENUM,
740 "ES3 texture parameters are not available without "
741 "GL_OES_EGL_image_external_essl3."));
742 return false;
743 }
744 break;
745
746 default:
747 break;
748 }
749
750 switch (pname)
751 {
752 case GL_TEXTURE_WRAP_S:
753 case GL_TEXTURE_WRAP_T:
754 case GL_TEXTURE_WRAP_R:
755 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
756 {
757 return false;
758 }
759 break;
760
761 case GL_TEXTURE_MIN_FILTER:
762 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
763 {
764 return false;
765 }
766 break;
767
768 case GL_TEXTURE_MAG_FILTER:
769 if (!ValidateTextureMagFilterValue(context, params))
770 {
771 return false;
772 }
773 break;
774
775 case GL_TEXTURE_USAGE_ANGLE:
776 switch (ConvertToGLenum(params[0]))
777 {
778 case GL_NONE:
779 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
780 break;
781
782 default:
783 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
784 return false;
785 }
786 break;
787
788 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
789 if (!context->getExtensions().textureFilterAnisotropic)
790 {
791 context->handleError(
792 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
793 return false;
794 }
795
796 // we assume the parameter passed to this validation method is truncated, not rounded
797 if (params[0] < 1)
798 {
799 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
800 return false;
801 }
802 break;
803
804 case GL_TEXTURE_MIN_LOD:
805 case GL_TEXTURE_MAX_LOD:
806 // any value is permissible
807 break;
808
809 case GL_TEXTURE_COMPARE_MODE:
810 if (!ValidateTextureCompareModeValue(context, params))
811 {
812 return false;
813 }
814 break;
815
816 case GL_TEXTURE_COMPARE_FUNC:
817 if (!ValidateTextureCompareFuncValue(context, params))
818 {
819 return false;
820 }
821 break;
822
823 case GL_TEXTURE_SWIZZLE_R:
824 case GL_TEXTURE_SWIZZLE_G:
825 case GL_TEXTURE_SWIZZLE_B:
826 case GL_TEXTURE_SWIZZLE_A:
827 switch (ConvertToGLenum(params[0]))
828 {
829 case GL_RED:
830 case GL_GREEN:
831 case GL_BLUE:
832 case GL_ALPHA:
833 case GL_ZERO:
834 case GL_ONE:
835 break;
836
837 default:
838 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
839 return false;
840 }
841 break;
842
843 case GL_TEXTURE_BASE_LEVEL:
844 if (params[0] < 0)
845 {
846 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
847 return false;
848 }
849 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
850 {
851 context->handleError(
852 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
853 return false;
854 }
855 break;
856
857 case GL_TEXTURE_MAX_LEVEL:
858 if (params[0] < 0)
859 {
860 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
861 return false;
862 }
863 break;
864
Geoff Lang3b573612016-10-31 14:08:10 -0400865 case GL_DEPTH_STENCIL_TEXTURE_MODE:
866 if (context->getClientVersion() < Version(3, 1))
867 {
868 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
869 return false;
870 }
Geoff Lang9f090372016-12-02 10:20:43 -0500871 switch (ConvertToGLenum(params[0]))
872 {
873 case GL_DEPTH_COMPONENT:
874 case GL_STENCIL_INDEX:
875 break;
876
877 default:
878 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
879 return false;
880 }
Geoff Lang3b573612016-10-31 14:08:10 -0400881 break;
882
Geoff Lang81c6b572016-10-19 14:07:52 -0700883 case GL_TEXTURE_SRGB_DECODE_EXT:
884 if (!ValidateTextureSRGBDecodeValue(context, params))
885 {
886 return false;
887 }
888 break;
889
Geoff Langc1984ed2016-10-07 12:41:00 -0400890 default:
891 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
892 return false;
893 }
894
895 return true;
896}
897
898template <typename ParamType>
899bool ValidateSamplerParameterBase(Context *context,
900 GLuint sampler,
901 GLenum pname,
902 GLsizei bufSize,
903 ParamType *params)
904{
905 if (context->getClientMajorVersion() < 3)
906 {
907 context->handleError(
908 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
909 return false;
910 }
911
912 if (!context->isSampler(sampler))
913 {
914 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
915 return false;
916 }
917
918 const GLsizei minBufSize = 1;
919 if (bufSize >= 0 && bufSize < minBufSize)
920 {
921 context->handleError(
922 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
923 return false;
924 }
925
926 switch (pname)
927 {
928 case GL_TEXTURE_WRAP_S:
929 case GL_TEXTURE_WRAP_T:
930 case GL_TEXTURE_WRAP_R:
931 if (!ValidateTextureWrapModeValue(context, params, false))
932 {
933 return false;
934 }
935 break;
936
937 case GL_TEXTURE_MIN_FILTER:
938 if (!ValidateTextureMinFilterValue(context, params, false))
939 {
940 return false;
941 }
942 break;
943
944 case GL_TEXTURE_MAG_FILTER:
945 if (!ValidateTextureMagFilterValue(context, params))
946 {
947 return false;
948 }
949 break;
950
951 case GL_TEXTURE_MIN_LOD:
952 case GL_TEXTURE_MAX_LOD:
953 // any value is permissible
954 break;
955
956 case GL_TEXTURE_COMPARE_MODE:
957 if (!ValidateTextureCompareModeValue(context, params))
958 {
959 return false;
960 }
961 break;
962
963 case GL_TEXTURE_COMPARE_FUNC:
964 if (!ValidateTextureCompareFuncValue(context, params))
965 {
966 return false;
967 }
968 break;
969
Geoff Lang81c6b572016-10-19 14:07:52 -0700970 case GL_TEXTURE_SRGB_DECODE_EXT:
971 if (!ValidateTextureSRGBDecodeValue(context, params))
972 {
973 return false;
974 }
975 break;
976
Geoff Langc1984ed2016-10-07 12:41:00 -0400977 default:
978 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
979 return false;
980 }
981
982 return true;
983}
984
985bool ValidateGetSamplerParameterBase(Context *context,
986 GLuint sampler,
987 GLenum pname,
988 GLsizei *length)
989{
990 if (length)
991 {
992 *length = 0;
993 }
994
995 if (context->getClientMajorVersion() < 3)
996 {
997 context->handleError(
998 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
999 return false;
1000 }
1001
1002 if (!context->isSampler(sampler))
1003 {
1004 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
1005 return false;
1006 }
1007
1008 switch (pname)
1009 {
1010 case GL_TEXTURE_WRAP_S:
1011 case GL_TEXTURE_WRAP_T:
1012 case GL_TEXTURE_WRAP_R:
1013 case GL_TEXTURE_MIN_FILTER:
1014 case GL_TEXTURE_MAG_FILTER:
1015 case GL_TEXTURE_MIN_LOD:
1016 case GL_TEXTURE_MAX_LOD:
1017 case GL_TEXTURE_COMPARE_MODE:
1018 case GL_TEXTURE_COMPARE_FUNC:
1019 break;
1020
Geoff Lang81c6b572016-10-19 14:07:52 -07001021 case GL_TEXTURE_SRGB_DECODE_EXT:
1022 if (!context->getExtensions().textureSRGBDecode)
1023 {
1024 context->handleError(
1025 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
1026 return false;
1027 }
1028 break;
1029
Geoff Langc1984ed2016-10-07 12:41:00 -04001030 default:
1031 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1032 return false;
1033 }
1034
1035 if (length)
1036 {
1037 *length = 1;
1038 }
1039 return true;
1040}
1041
Geoff Lang0b031062016-10-13 14:30:04 -04001042bool ValidateGetVertexAttribBase(Context *context,
1043 GLuint index,
1044 GLenum pname,
1045 GLsizei *length,
1046 bool pointer,
1047 bool pureIntegerEntryPoint)
1048{
1049 if (length)
1050 {
1051 *length = 0;
1052 }
1053
1054 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1055 {
1056 context->handleError(
1057 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1058 return false;
1059 }
1060
1061 if (index >= context->getCaps().maxVertexAttributes)
1062 {
1063 context->handleError(Error(
1064 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1065 return false;
1066 }
1067
1068 if (pointer)
1069 {
1070 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1071 {
1072 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1073 return false;
1074 }
1075 }
1076 else
1077 {
1078 switch (pname)
1079 {
1080 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1081 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1082 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1083 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1084 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1085 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1086 case GL_CURRENT_VERTEX_ATTRIB:
1087 break;
1088
1089 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1090 static_assert(
1091 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1092 "ANGLE extension enums not equal to GL enums.");
1093 if (context->getClientMajorVersion() < 3 &&
1094 !context->getExtensions().instancedArrays)
1095 {
1096 context->handleError(Error(GL_INVALID_ENUM,
1097 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1098 "3.0 or GL_ANGLE_instanced_arrays."));
1099 return false;
1100 }
1101 break;
1102
1103 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1104 if (context->getClientMajorVersion() < 3)
1105 {
1106 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1107 return false;
1108 }
1109 break;
1110
1111 default:
1112 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1113 return false;
1114 }
1115 }
1116
1117 if (length)
1118 {
1119 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1120 {
1121 *length = 4;
1122 }
1123 else
1124 {
1125 *length = 1;
1126 }
1127 }
1128
1129 return true;
1130}
1131
Geoff Lang6899b872016-10-14 11:30:13 -04001132bool ValidateGetActiveUniformBlockivBase(Context *context,
1133 GLuint program,
1134 GLuint uniformBlockIndex,
1135 GLenum pname,
1136 GLsizei *length)
1137{
1138 if (length)
1139 {
1140 *length = 0;
1141 }
1142
1143 if (context->getClientMajorVersion() < 3)
1144 {
1145 context->handleError(
1146 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1147 return false;
1148 }
1149
1150 Program *programObject = GetValidProgram(context, program);
1151 if (!programObject)
1152 {
1153 return false;
1154 }
1155
1156 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1157 {
1158 context->handleError(
1159 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1160 return false;
1161 }
1162
1163 switch (pname)
1164 {
1165 case GL_UNIFORM_BLOCK_BINDING:
1166 case GL_UNIFORM_BLOCK_DATA_SIZE:
1167 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1168 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1169 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1170 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1171 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1172 break;
1173
1174 default:
1175 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1176 return false;
1177 }
1178
1179 if (length)
1180 {
1181 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1182 {
1183 const UniformBlock &uniformBlock =
1184 programObject->getUniformBlockByIndex(uniformBlockIndex);
1185 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1186 }
1187 else
1188 {
1189 *length = 1;
1190 }
1191 }
1192
1193 return true;
1194}
1195
Geoff Langebebe1c2016-10-14 12:01:31 -04001196bool ValidateGetBufferParameterBase(ValidationContext *context,
1197 GLenum target,
1198 GLenum pname,
1199 bool pointerVersion,
1200 GLsizei *numParams)
1201{
1202 if (numParams)
1203 {
1204 *numParams = 0;
1205 }
1206
1207 if (!ValidBufferTarget(context, target))
1208 {
1209 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1210 return false;
1211 }
1212
1213 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1214 if (!buffer)
1215 {
1216 // A null buffer means that "0" is bound to the requested buffer target
1217 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1218 return false;
1219 }
1220
1221 const Extensions &extensions = context->getExtensions();
1222
1223 switch (pname)
1224 {
1225 case GL_BUFFER_USAGE:
1226 case GL_BUFFER_SIZE:
1227 break;
1228
1229 case GL_BUFFER_ACCESS_OES:
1230 if (!extensions.mapBuffer)
1231 {
1232 context->handleError(
Jamie Madillcc6ac252017-01-25 12:57:21 -08001233 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001234 return false;
1235 }
1236 break;
1237
1238 case GL_BUFFER_MAPPED:
1239 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1240 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1241 !extensions.mapBufferRange)
1242 {
1243 context->handleError(Error(
1244 GL_INVALID_ENUM,
Jamie Madillcc6ac252017-01-25 12:57:21 -08001245 "pname requires OpenGL ES 3.0, GL_OES_mapbuffer or GL_EXT_map_buffer_range."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001246 return false;
1247 }
1248 break;
1249
1250 case GL_BUFFER_MAP_POINTER:
1251 if (!pointerVersion)
1252 {
1253 context->handleError(
1254 Error(GL_INVALID_ENUM,
1255 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1256 return false;
1257 }
1258 break;
1259
1260 case GL_BUFFER_ACCESS_FLAGS:
1261 case GL_BUFFER_MAP_OFFSET:
1262 case GL_BUFFER_MAP_LENGTH:
1263 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1264 {
1265 context->handleError(Error(
1266 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1267 return false;
1268 }
1269 break;
1270
1271 default:
1272 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1273 return false;
1274 }
1275
1276 // All buffer parameter queries return one value.
1277 if (numParams)
1278 {
1279 *numParams = 1;
1280 }
1281
1282 return true;
1283}
1284
Geoff Lang0a9661f2016-10-20 10:59:20 -07001285bool ValidateGetInternalFormativBase(Context *context,
1286 GLenum target,
1287 GLenum internalformat,
1288 GLenum pname,
1289 GLsizei bufSize,
1290 GLsizei *numParams)
1291{
1292 if (numParams)
1293 {
1294 *numParams = 0;
1295 }
1296
1297 if (context->getClientMajorVersion() < 3)
1298 {
1299 context->handleError(
1300 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1301 return false;
1302 }
1303
1304 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1305 if (!formatCaps.renderable)
1306 {
1307 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1308 return false;
1309 }
1310
1311 switch (target)
1312 {
1313 case GL_RENDERBUFFER:
1314 break;
1315
JiangYizhoubddc46b2016-12-09 09:50:51 +08001316 case GL_TEXTURE_2D_MULTISAMPLE:
1317 if (context->getClientVersion() < ES_3_1)
1318 {
1319 context->handleError(
1320 Error(GL_INVALID_OPERATION, "Texture target requires at least OpenGL ES 3.1."));
1321 return false;
1322 }
1323 break;
1324
Geoff Lang0a9661f2016-10-20 10:59:20 -07001325 default:
1326 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1327 return false;
1328 }
1329
1330 if (bufSize < 0)
1331 {
1332 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1333 return false;
1334 }
1335
1336 GLsizei maxWriteParams = 0;
1337 switch (pname)
1338 {
1339 case GL_NUM_SAMPLE_COUNTS:
1340 maxWriteParams = 1;
1341 break;
1342
1343 case GL_SAMPLES:
1344 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1345 break;
1346
1347 default:
1348 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1349 return false;
1350 }
1351
1352 if (numParams)
1353 {
1354 // glGetInternalFormativ will not overflow bufSize
1355 *numParams = std::min(bufSize, maxWriteParams);
1356 }
1357
1358 return true;
1359}
1360
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001361bool ValidateUniformCommonBase(gl::Context *context,
1362 gl::Program *program,
1363 GLint location,
1364 GLsizei count,
1365 const LinkedUniform **uniformOut)
1366{
1367 // TODO(Jiajia): Add image uniform check in future.
1368 if (count < 0)
1369 {
1370 context->handleError(Error(GL_INVALID_VALUE));
1371 return false;
1372 }
1373
1374 if (!program || !program->isLinked())
1375 {
1376 context->handleError(Error(GL_INVALID_OPERATION));
1377 return false;
1378 }
1379
1380 if (location == -1)
1381 {
1382 // Silently ignore the uniform command
1383 return false;
1384 }
1385
1386 const auto &uniformLocations = program->getUniformLocations();
1387 size_t castedLocation = static_cast<size_t>(location);
1388 if (castedLocation >= uniformLocations.size())
1389 {
1390 context->handleError(Error(GL_INVALID_OPERATION, "Invalid uniform location"));
1391 return false;
1392 }
1393
1394 const auto &uniformLocation = uniformLocations[castedLocation];
1395 if (uniformLocation.ignored)
1396 {
1397 // Silently ignore the uniform command
1398 return false;
1399 }
1400
1401 if (!uniformLocation.used)
1402 {
1403 context->handleError(Error(GL_INVALID_OPERATION));
1404 return false;
1405 }
1406
1407 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
1408
1409 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
1410 if (!uniform.isArray() && count > 1)
1411 {
1412 context->handleError(Error(GL_INVALID_OPERATION));
1413 return false;
1414 }
1415
1416 *uniformOut = &uniform;
1417 return true;
1418}
1419
1420bool ValidateUniformValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1421{
1422 // Check that the value type is compatible with uniform type.
1423 // Do the cheaper tests first, for a little extra speed.
1424 if (valueType == uniformType || (valueType == GL_INT && IsSamplerType(uniformType)) ||
1425 VariableBoolVectorType(valueType) == uniformType)
1426 {
1427 return true;
1428 }
1429
1430 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1431 return false;
1432}
1433
1434bool ValidateUniformMatrixValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1435{
1436 // Check that the value type is compatible with uniform type.
1437 if (valueType == uniformType)
1438 {
1439 return true;
1440 }
1441
1442 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1443 return false;
1444}
1445
Geoff Langf41a7152016-09-19 15:11:17 -04001446} // anonymous namespace
1447
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001448bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001449{
Jamie Madilld7460c72014-01-21 16:38:14 -05001450 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001451 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001452 case GL_TEXTURE_2D:
1453 case GL_TEXTURE_CUBE_MAP:
1454 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001455
He Yunchaoced53ae2016-11-29 15:00:51 +08001456 case GL_TEXTURE_3D:
1457 case GL_TEXTURE_2D_ARRAY:
1458 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001459
He Yunchaoced53ae2016-11-29 15:00:51 +08001460 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001461 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001462
He Yunchaoced53ae2016-11-29 15:00:51 +08001463 default:
1464 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001465 }
Jamie Madill35d15012013-10-07 10:46:37 -04001466}
1467
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001468bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1469{
1470 switch (target)
1471 {
1472 case GL_TEXTURE_2D:
1473 case GL_TEXTURE_CUBE_MAP:
1474 return true;
1475
1476 default:
1477 return false;
1478 }
1479}
1480
1481bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1482{
1483 switch (target)
1484 {
1485 case GL_TEXTURE_3D:
1486 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001487 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001488
1489 default:
1490 return false;
1491 }
1492}
1493
Ian Ewellbda75592016-04-18 17:25:54 -04001494// Most texture GL calls are not compatible with external textures, so we have a separate validation
1495// function for use in the GL calls that do
1496bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1497{
1498 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1499 (context->getExtensions().eglImageExternal ||
1500 context->getExtensions().eglStreamConsumerExternal);
1501}
1502
Shannon Woods4dfed832014-03-17 20:03:39 -04001503// This function differs from ValidTextureTarget in that the target must be
1504// usable as the destination of a 2D operation-- so a cube face is valid, but
1505// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001506// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001507bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001508{
1509 switch (target)
1510 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001511 case GL_TEXTURE_2D:
1512 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1513 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1514 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1515 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1516 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1517 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1518 return true;
1519 default:
1520 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001521 }
1522}
1523
1524bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1525{
1526 switch (target)
1527 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001528 case GL_TEXTURE_3D:
1529 case GL_TEXTURE_2D_ARRAY:
1530 return true;
1531 default:
1532 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001533 }
1534}
1535
He Yunchao11b038b2016-11-22 21:24:04 +08001536bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1537{
1538 switch (target)
1539 {
1540 case GL_TEXTURE_2D:
1541 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1542 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1543 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1544 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1545 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1546 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1547 case GL_TEXTURE_3D:
1548 case GL_TEXTURE_2D_ARRAY:
1549 case GL_TEXTURE_2D_MULTISAMPLE:
1550 return true;
1551 default:
1552 return false;
1553 }
1554}
1555
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001556bool ValidFramebufferTarget(GLenum target)
1557{
He Yunchaoced53ae2016-11-29 15:00:51 +08001558 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1559 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001560 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001561
1562 switch (target)
1563 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001564 case GL_FRAMEBUFFER:
1565 return true;
1566 case GL_READ_FRAMEBUFFER:
1567 return true;
1568 case GL_DRAW_FRAMEBUFFER:
1569 return true;
1570 default:
1571 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001572 }
1573}
1574
Jamie Madill29639852016-09-02 15:00:09 -04001575bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001576{
1577 switch (target)
1578 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001579 case GL_ARRAY_BUFFER:
1580 case GL_ELEMENT_ARRAY_BUFFER:
1581 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001582
He Yunchaoced53ae2016-11-29 15:00:51 +08001583 case GL_PIXEL_PACK_BUFFER:
1584 case GL_PIXEL_UNPACK_BUFFER:
1585 return (context->getExtensions().pixelBufferObject ||
1586 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001587
He Yunchaoced53ae2016-11-29 15:00:51 +08001588 case GL_COPY_READ_BUFFER:
1589 case GL_COPY_WRITE_BUFFER:
1590 case GL_TRANSFORM_FEEDBACK_BUFFER:
1591 case GL_UNIFORM_BUFFER:
1592 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001593
He Yunchaoced53ae2016-11-29 15:00:51 +08001594 case GL_ATOMIC_COUNTER_BUFFER:
1595 case GL_SHADER_STORAGE_BUFFER:
1596 case GL_DRAW_INDIRECT_BUFFER:
1597 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001598 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001599
He Yunchaoced53ae2016-11-29 15:00:51 +08001600 default:
1601 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001602 }
1603}
1604
Jamie Madillc29968b2016-01-20 11:17:23 -05001605bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001606{
Jamie Madillc29968b2016-01-20 11:17:23 -05001607 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001608 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001609 switch (target)
1610 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001611 case GL_TEXTURE_2D:
1612 maxDimension = caps.max2DTextureSize;
1613 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001614 case GL_TEXTURE_CUBE_MAP:
1615 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1616 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1617 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1618 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1619 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1620 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1621 maxDimension = caps.maxCubeMapTextureSize;
1622 break;
1623 case GL_TEXTURE_3D:
1624 maxDimension = caps.max3DTextureSize;
1625 break;
1626 case GL_TEXTURE_2D_ARRAY:
1627 maxDimension = caps.max2DTextureSize;
1628 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001629 case GL_TEXTURE_2D_MULTISAMPLE:
1630 maxDimension = caps.max2DTextureSize;
1631 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001632 default:
1633 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001634 }
1635
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001636 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001637}
1638
Geoff Langcc507aa2016-12-12 10:09:52 -05001639bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001640 GLenum target,
1641 GLint level,
1642 GLsizei width,
1643 GLsizei height,
1644 GLsizei depth,
1645 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001646{
1647 if (level < 0 || width < 0 || height < 0 || depth < 0)
1648 {
1649 return false;
1650 }
1651
Austin Kinross08528e12015-10-07 16:24:40 -07001652 // TexSubImage parameters can be NPOT without textureNPOT extension,
1653 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001654 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001655 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001656 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001657 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001658 {
1659 return false;
1660 }
1661
1662 if (!ValidMipLevel(context, target, level))
1663 {
1664 return false;
1665 }
1666
1667 return true;
1668}
1669
Geoff Lang0d8b7242015-09-09 14:56:53 -04001670bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1671{
1672 // List of compressed format that require that the texture size is smaller than or a multiple of
1673 // the compressed block size.
1674 switch (internalFormat)
1675 {
1676 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1677 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1678 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1679 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001680 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001681 return true;
1682
1683 default:
1684 return false;
1685 }
1686}
1687
Jamie Madillc29968b2016-01-20 11:17:23 -05001688bool ValidCompressedImageSize(const ValidationContext *context,
1689 GLenum internalFormat,
1690 GLsizei width,
1691 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001692{
Geoff Lang5d601382014-07-22 15:14:06 -04001693 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1694 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001695 {
1696 return false;
1697 }
1698
Geoff Lang0d8b7242015-09-09 14:56:53 -04001699 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001700 {
1701 return false;
1702 }
1703
Geoff Lang0d8b7242015-09-09 14:56:53 -04001704 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1705 {
1706 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1707 width % formatInfo.compressedBlockWidth != 0) ||
1708 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1709 height % formatInfo.compressedBlockHeight != 0))
1710 {
1711 return false;
1712 }
1713 }
1714
Geoff Langd4f180b2013-09-24 13:57:44 -04001715 return true;
1716}
1717
Geoff Langff5b2d52016-09-07 11:32:23 -04001718bool ValidImageDataSize(ValidationContext *context,
1719 GLenum textureTarget,
1720 GLsizei width,
1721 GLsizei height,
1722 GLsizei depth,
1723 GLenum internalFormat,
1724 GLenum type,
1725 const GLvoid *pixels,
1726 GLsizei imageSize)
1727{
1728 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1729 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1730 {
1731 // Checks are not required
1732 return true;
1733 }
1734
1735 // ...the data would be unpacked from the buffer object such that the memory reads required
1736 // would exceed the data store size.
1737 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1738 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1739 const gl::Extents size(width, height, depth);
1740 const auto &unpack = context->getGLState().getUnpackState();
1741
1742 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1743 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1744 if (endByteOrErr.isError())
1745 {
1746 context->handleError(endByteOrErr.getError());
1747 return false;
1748 }
1749
1750 GLuint endByte = endByteOrErr.getResult();
1751
1752 if (pixelUnpackBuffer)
1753 {
1754 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1755 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1756 checkedEndByte += checkedOffset;
1757
1758 if (!checkedEndByte.IsValid() ||
1759 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1760 {
1761 // Overflow past the end of the buffer
1762 context->handleError(Error(GL_INVALID_OPERATION));
1763 return false;
1764 }
1765 }
1766 else
1767 {
1768 ASSERT(imageSize >= 0);
1769 if (pixels == nullptr && imageSize != 0)
1770 {
1771 context->handleError(
1772 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001773 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001774 }
1775
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001776 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001777 {
1778 context->handleError(
1779 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1780 return false;
1781 }
1782 }
1783
1784 return true;
1785}
1786
Geoff Lang37dde692014-01-31 16:34:54 -05001787bool ValidQueryType(const Context *context, GLenum queryType)
1788{
He Yunchaoced53ae2016-11-29 15:00:51 +08001789 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1790 "GL extension enums not equal.");
1791 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1792 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001793
1794 switch (queryType)
1795 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001796 case GL_ANY_SAMPLES_PASSED:
1797 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1798 return true;
1799 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1800 return (context->getClientMajorVersion() >= 3);
1801 case GL_TIME_ELAPSED_EXT:
1802 return context->getExtensions().disjointTimerQuery;
1803 case GL_COMMANDS_COMPLETED_CHROMIUM:
1804 return context->getExtensions().syncQuery;
1805 default:
1806 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001807 }
1808}
1809
Jamie Madillef300b12016-10-07 15:12:09 -04001810Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001811{
He Yunchaoced53ae2016-11-29 15:00:51 +08001812 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1813 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1814 // or program object and INVALID_OPERATION if the provided name identifies an object
1815 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001816
Dian Xiang769769a2015-09-09 15:20:08 -07001817 Program *validProgram = context->getProgram(id);
1818
1819 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001820 {
Dian Xiang769769a2015-09-09 15:20:08 -07001821 if (context->getShader(id))
1822 {
Jamie Madill437fa652016-05-03 15:13:24 -04001823 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001824 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1825 }
1826 else
1827 {
Jamie Madill437fa652016-05-03 15:13:24 -04001828 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001829 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001830 }
Dian Xiang769769a2015-09-09 15:20:08 -07001831
1832 return validProgram;
1833}
1834
Jamie Madillef300b12016-10-07 15:12:09 -04001835Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001836{
1837 // See ValidProgram for spec details.
1838
1839 Shader *validShader = context->getShader(id);
1840
1841 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001842 {
Dian Xiang769769a2015-09-09 15:20:08 -07001843 if (context->getProgram(id))
1844 {
Jamie Madill437fa652016-05-03 15:13:24 -04001845 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001846 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1847 }
1848 else
1849 {
Jamie Madill437fa652016-05-03 15:13:24 -04001850 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001851 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001852 }
Dian Xiang769769a2015-09-09 15:20:08 -07001853
1854 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001855}
1856
Geoff Langb1196682014-07-23 13:47:29 -04001857bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001858{
1859 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1860 {
1861 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1862
Geoff Langaae65a42014-05-26 12:43:44 -04001863 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001864 {
Jamie Madill437fa652016-05-03 15:13:24 -04001865 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001866 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001867 }
1868 }
1869 else
1870 {
1871 switch (attachment)
1872 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001873 case GL_DEPTH_ATTACHMENT:
1874 case GL_STENCIL_ATTACHMENT:
1875 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001876
He Yunchaoced53ae2016-11-29 15:00:51 +08001877 case GL_DEPTH_STENCIL_ATTACHMENT:
1878 if (!context->getExtensions().webglCompatibility &&
1879 context->getClientMajorVersion() < 3)
1880 {
1881 context->handleError(Error(GL_INVALID_ENUM));
1882 return false;
1883 }
1884 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001885
He Yunchaoced53ae2016-11-29 15:00:51 +08001886 default:
1887 context->handleError(Error(GL_INVALID_ENUM));
1888 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001889 }
1890 }
1891
1892 return true;
1893}
1894
He Yunchaoced53ae2016-11-29 15:00:51 +08001895bool ValidateRenderbufferStorageParametersBase(gl::Context *context,
1896 GLenum target,
1897 GLsizei samples,
1898 GLenum internalformat,
1899 GLsizei width,
1900 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001901{
1902 switch (target)
1903 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001904 case GL_RENDERBUFFER:
1905 break;
1906 default:
1907 context->handleError(Error(GL_INVALID_ENUM));
1908 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001909 }
1910
1911 if (width < 0 || height < 0 || samples < 0)
1912 {
Jamie Madill437fa652016-05-03 15:13:24 -04001913 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001914 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001915 }
1916
Geoff Langd87878e2014-09-19 15:42:59 -04001917 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1918 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001919 {
Jamie Madill437fa652016-05-03 15:13:24 -04001920 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001921 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001922 }
1923
1924 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1925 // 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 -08001926 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001927 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001928 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001929 {
Jamie Madill437fa652016-05-03 15:13:24 -04001930 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001931 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001932 }
1933
Geoff Langaae65a42014-05-26 12:43:44 -04001934 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001935 {
Jamie Madill437fa652016-05-03 15:13:24 -04001936 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001937 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001938 }
1939
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001940 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001941 if (handle == 0)
1942 {
Jamie Madill437fa652016-05-03 15:13:24 -04001943 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001944 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001945 }
1946
1947 return true;
1948}
1949
He Yunchaoced53ae2016-11-29 15:00:51 +08001950bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context,
1951 GLenum target,
1952 GLsizei samples,
1953 GLenum internalformat,
1954 GLsizei width,
1955 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -08001956{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001957 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001958
1959 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001960 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001961 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001962 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001963 {
Jamie Madill437fa652016-05-03 15:13:24 -04001964 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001965 return false;
1966 }
1967
1968 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1969 // the specified storage. This is different than ES 3.0 in which a sample number higher
1970 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001971 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001972 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001973 {
Geoff Langa4903b72015-03-02 16:02:48 -08001974 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1975 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1976 {
Jamie Madill437fa652016-05-03 15:13:24 -04001977 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001978 return false;
1979 }
Corentin Walleze0902642014-11-04 12:32:15 -08001980 }
1981
He Yunchaoced53ae2016-11-29 15:00:51 +08001982 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
1983 width, height);
Corentin Walleze0902642014-11-04 12:32:15 -08001984}
1985
He Yunchaoced53ae2016-11-29 15:00:51 +08001986bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1987 GLenum target,
1988 GLenum attachment,
1989 GLenum renderbuffertarget,
1990 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001991{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001992 if (!ValidFramebufferTarget(target))
1993 {
Jamie Madill437fa652016-05-03 15:13:24 -04001994 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001995 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001996 }
1997
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001998 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001999
Jamie Madill84115c92015-04-23 15:00:07 -04002000 ASSERT(framebuffer);
2001 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002002 {
Jamie Madill437fa652016-05-03 15:13:24 -04002003 context->handleError(
2004 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002005 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002006 }
2007
Jamie Madillb4472272014-07-03 10:38:55 -04002008 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002009 {
Jamie Madillb4472272014-07-03 10:38:55 -04002010 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002011 }
2012
Jamie Madillab9d82c2014-01-21 16:38:14 -05002013 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2014 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2015 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2016 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2017 if (renderbuffer != 0)
2018 {
2019 if (!context->getRenderbuffer(renderbuffer))
2020 {
Jamie Madill437fa652016-05-03 15:13:24 -04002021 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002022 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05002023 }
2024 }
2025
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002026 return true;
2027}
2028
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002029bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002030 GLint srcX0,
2031 GLint srcY0,
2032 GLint srcX1,
2033 GLint srcY1,
2034 GLint dstX0,
2035 GLint dstY0,
2036 GLint dstX1,
2037 GLint dstY1,
2038 GLbitfield mask,
2039 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002040{
2041 switch (filter)
2042 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002043 case GL_NEAREST:
2044 break;
2045 case GL_LINEAR:
2046 break;
2047 default:
2048 context->handleError(Error(GL_INVALID_ENUM));
2049 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002050 }
2051
2052 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
2053 {
Jamie Madill437fa652016-05-03 15:13:24 -04002054 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002055 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002056 }
2057
2058 if (mask == 0)
2059 {
2060 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
2061 // buffers are copied.
2062 return false;
2063 }
2064
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002065 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
2066 // color buffer, leaving only nearest being unfiltered from above
2067 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
2068 {
Jamie Madill437fa652016-05-03 15:13:24 -04002069 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002070 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002071 }
2072
Jamie Madill51f40ec2016-06-15 14:06:00 -04002073 const auto &glState = context->getGLState();
2074 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2075 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05002076
2077 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002078 {
Jamie Madill437fa652016-05-03 15:13:24 -04002079 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002080 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002081 }
2082
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002083 if (readFramebuffer->id() == drawFramebuffer->id())
2084 {
2085 context->handleError(Error(GL_INVALID_OPERATION));
2086 return false;
2087 }
2088
Jamie Madill51f40ec2016-06-15 14:06:00 -04002089 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002090 {
Jamie Madill437fa652016-05-03 15:13:24 -04002091 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002092 return false;
2093 }
2094
Jamie Madill51f40ec2016-06-15 14:06:00 -04002095 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002096 {
Jamie Madill437fa652016-05-03 15:13:24 -04002097 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002098 return false;
2099 }
2100
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002101 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002102 {
Jamie Madill437fa652016-05-03 15:13:24 -04002103 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002104 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002105 }
2106
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002107 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2108
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002109 if (mask & GL_COLOR_BUFFER_BIT)
2110 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002111 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002112 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002113
He Yunchao66a41a22016-12-15 16:45:05 +08002114 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002115 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002116 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002117
Geoff Langa15472a2015-08-11 11:48:03 -04002118 for (size_t drawbufferIdx = 0;
2119 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002120 {
Geoff Langa15472a2015-08-11 11:48:03 -04002121 const FramebufferAttachment *attachment =
2122 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2123 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002124 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002125 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002126
Geoff Langb2f3d052013-08-13 12:49:27 -04002127 // The GL ES 3.0.2 spec (pg 193) states that:
2128 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002129 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2130 // as well
2131 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2132 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002133 // Changes with EXT_color_buffer_float:
2134 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002135 GLenum readComponentType = readFormat.info->componentType;
2136 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002137 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002138 readComponentType == GL_SIGNED_NORMALIZED);
2139 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2140 drawComponentType == GL_SIGNED_NORMALIZED);
2141
2142 if (extensions.colorBufferFloat)
2143 {
2144 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2145 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2146
2147 if (readFixedOrFloat != drawFixedOrFloat)
2148 {
Jamie Madill437fa652016-05-03 15:13:24 -04002149 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002150 "If the read buffer contains fixed-point or "
2151 "floating-point values, the draw buffer "
2152 "must as well."));
2153 return false;
2154 }
2155 }
2156 else if (readFixedPoint != drawFixedPoint)
2157 {
Jamie Madill437fa652016-05-03 15:13:24 -04002158 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002159 "If the read buffer contains fixed-point "
2160 "values, the draw buffer must as well."));
2161 return false;
2162 }
2163
2164 if (readComponentType == GL_UNSIGNED_INT &&
2165 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002166 {
Jamie Madill437fa652016-05-03 15:13:24 -04002167 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002168 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002169 }
2170
Jamie Madill6163c752015-12-07 16:32:59 -05002171 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002172 {
Jamie Madill437fa652016-05-03 15:13:24 -04002173 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002174 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002175 }
2176
Jamie Madilla3944d42016-07-22 22:13:26 -04002177 if (readColorBuffer->getSamples() > 0 &&
2178 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002179 {
Jamie Madill437fa652016-05-03 15:13:24 -04002180 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002181 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002182 }
2183 }
2184 }
2185
Jamie Madilla3944d42016-07-22 22:13:26 -04002186 if ((readFormat.info->componentType == GL_INT ||
2187 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2188 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002189 {
Jamie Madill437fa652016-05-03 15:13:24 -04002190 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002191 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002192 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002193 }
He Yunchao66a41a22016-12-15 16:45:05 +08002194 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2195 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2196 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2197 // situation is an application error that would lead to a crash in ANGLE.
2198 else if (drawFramebuffer->hasEnabledDrawBuffer())
2199 {
2200 context->handleError(Error(
2201 GL_INVALID_OPERATION,
2202 "Attempt to read from a missing color attachment of a complete framebuffer."));
2203 return false;
2204 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002205 }
2206
He Yunchaoced53ae2016-11-29 15:00:51 +08002207 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002208 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2209 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002210 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002211 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002212 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002213 const gl::FramebufferAttachment *readBuffer =
2214 readFramebuffer->getAttachment(attachments[i]);
2215 const gl::FramebufferAttachment *drawBuffer =
2216 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002217
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002218 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002219 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002220 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002221 {
Jamie Madill437fa652016-05-03 15:13:24 -04002222 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002223 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002224 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002225
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002226 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002227 {
Jamie Madill437fa652016-05-03 15:13:24 -04002228 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002229 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002230 }
2231 }
He Yunchao66a41a22016-12-15 16:45:05 +08002232 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2233 else if (drawBuffer)
2234 {
2235 context->handleError(Error(GL_INVALID_OPERATION,
2236 "Attempt to read from a missing depth/stencil "
2237 "attachment of a complete framebuffer."));
2238 return false;
2239 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002240 }
2241 }
2242
2243 return true;
2244}
2245
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002246bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002247 GLint x,
2248 GLint y,
2249 GLsizei width,
2250 GLsizei height,
2251 GLenum format,
2252 GLenum type,
2253 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002254{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002255 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2256}
2257
2258bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2259 GLint x,
2260 GLint y,
2261 GLsizei width,
2262 GLsizei height,
2263 GLenum format,
2264 GLenum type,
2265 GLsizei bufSize,
2266 GLsizei *length,
2267 GLvoid *pixels)
2268{
2269 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002270 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002271 return false;
2272 }
2273
Geoff Lang62fce5b2016-09-30 10:46:35 -04002274 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2275 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002276 {
Geoff Langb1196682014-07-23 13:47:29 -04002277 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002278 }
2279
Geoff Lang62fce5b2016-09-30 10:46:35 -04002280 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002281 {
Geoff Langb1196682014-07-23 13:47:29 -04002282 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002283 }
2284
Jamie Madillc29968b2016-01-20 11:17:23 -05002285 return true;
2286}
2287
2288bool ValidateReadnPixelsEXT(Context *context,
2289 GLint x,
2290 GLint y,
2291 GLsizei width,
2292 GLsizei height,
2293 GLenum format,
2294 GLenum type,
2295 GLsizei bufSize,
2296 GLvoid *pixels)
2297{
2298 if (bufSize < 0)
2299 {
Jamie Madill437fa652016-05-03 15:13:24 -04002300 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002301 return false;
2302 }
2303
Geoff Lang62fce5b2016-09-30 10:46:35 -04002304 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2305 pixels);
2306}
Jamie Madill26e91952014-03-05 15:01:27 -05002307
Geoff Lang62fce5b2016-09-30 10:46:35 -04002308bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2309 GLint x,
2310 GLint y,
2311 GLsizei width,
2312 GLsizei height,
2313 GLenum format,
2314 GLenum type,
2315 GLsizei bufSize,
2316 GLsizei *length,
2317 GLvoid *data)
2318{
2319 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002320 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002321 return false;
2322 }
2323
Geoff Lang62fce5b2016-09-30 10:46:35 -04002324 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002325 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002326 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002327 }
2328
Geoff Lang62fce5b2016-09-30 10:46:35 -04002329 if (!ValidateRobustBufferSize(context, bufSize, *length))
2330 {
2331 return false;
2332 }
2333
2334 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002335}
2336
Olli Etuaho41997e72016-03-10 13:38:39 +02002337bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002338{
2339 if (!context->getExtensions().occlusionQueryBoolean &&
2340 !context->getExtensions().disjointTimerQuery)
2341 {
Jamie Madill437fa652016-05-03 15:13:24 -04002342 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002343 return false;
2344 }
2345
Olli Etuaho41997e72016-03-10 13:38:39 +02002346 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002347}
2348
Olli Etuaho41997e72016-03-10 13:38:39 +02002349bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002350{
2351 if (!context->getExtensions().occlusionQueryBoolean &&
2352 !context->getExtensions().disjointTimerQuery)
2353 {
Jamie Madill437fa652016-05-03 15:13:24 -04002354 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002355 return false;
2356 }
2357
Olli Etuaho41997e72016-03-10 13:38:39 +02002358 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002359}
2360
2361bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002362{
2363 if (!ValidQueryType(context, target))
2364 {
Jamie Madill437fa652016-05-03 15:13:24 -04002365 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002366 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002367 }
2368
2369 if (id == 0)
2370 {
Jamie Madill437fa652016-05-03 15:13:24 -04002371 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002372 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002373 }
2374
2375 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2376 // of zero, if the active query object name for <target> is non-zero (for the
2377 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2378 // the active query for either target is non-zero), if <id> is the name of an
2379 // existing query object whose type does not match <target>, or if <id> is the
2380 // active query object name for any query type, the error INVALID_OPERATION is
2381 // generated.
2382
2383 // Ensure no other queries are active
2384 // NOTE: If other queries than occlusion are supported, we will need to check
2385 // separately that:
2386 // a) The query ID passed is not the current active query for any target/type
2387 // b) There are no active queries for the requested target (and in the case
2388 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2389 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002390
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002391 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002392 {
Jamie Madill437fa652016-05-03 15:13:24 -04002393 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002394 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002395 }
2396
2397 Query *queryObject = context->getQuery(id, true, target);
2398
2399 // check that name was obtained with glGenQueries
2400 if (!queryObject)
2401 {
Jamie Madill437fa652016-05-03 15:13:24 -04002402 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002403 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002404 }
2405
2406 // check for type mismatch
2407 if (queryObject->getType() != target)
2408 {
Jamie Madill437fa652016-05-03 15:13:24 -04002409 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002410 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002411 }
2412
2413 return true;
2414}
2415
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002416bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2417{
2418 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002419 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002420 {
Jamie Madill437fa652016-05-03 15:13:24 -04002421 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002422 return false;
2423 }
2424
2425 return ValidateBeginQueryBase(context, target, id);
2426}
2427
2428bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002429{
2430 if (!ValidQueryType(context, target))
2431 {
Jamie Madill437fa652016-05-03 15:13:24 -04002432 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002433 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002434 }
2435
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002436 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002437
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002438 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002439 {
Jamie Madill437fa652016-05-03 15:13:24 -04002440 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002441 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002442 }
2443
Jamie Madill45c785d2014-05-13 14:09:34 -04002444 return true;
2445}
2446
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002447bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2448{
2449 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002450 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002451 {
Jamie Madill437fa652016-05-03 15:13:24 -04002452 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002453 return false;
2454 }
2455
2456 return ValidateEndQueryBase(context, target);
2457}
2458
2459bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2460{
2461 if (!context->getExtensions().disjointTimerQuery)
2462 {
Jamie Madill437fa652016-05-03 15:13:24 -04002463 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002464 return false;
2465 }
2466
2467 if (target != GL_TIMESTAMP_EXT)
2468 {
Jamie Madill437fa652016-05-03 15:13:24 -04002469 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002470 return false;
2471 }
2472
2473 Query *queryObject = context->getQuery(id, true, target);
2474 if (queryObject == nullptr)
2475 {
Jamie Madill437fa652016-05-03 15:13:24 -04002476 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002477 return false;
2478 }
2479
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002480 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002481 {
Jamie Madill437fa652016-05-03 15:13:24 -04002482 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002483 return false;
2484 }
2485
2486 return true;
2487}
2488
Geoff Lang2186c382016-10-14 10:54:54 -04002489bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002490{
Geoff Lang2186c382016-10-14 10:54:54 -04002491 if (numParams)
2492 {
2493 *numParams = 0;
2494 }
2495
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002496 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2497 {
Jamie Madill437fa652016-05-03 15:13:24 -04002498 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002499 return false;
2500 }
2501
2502 switch (pname)
2503 {
2504 case GL_CURRENT_QUERY_EXT:
2505 if (target == GL_TIMESTAMP_EXT)
2506 {
Jamie Madill437fa652016-05-03 15:13:24 -04002507 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002508 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2509 return false;
2510 }
2511 break;
2512 case GL_QUERY_COUNTER_BITS_EXT:
2513 if (!context->getExtensions().disjointTimerQuery ||
2514 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2515 {
Jamie Madill437fa652016-05-03 15:13:24 -04002516 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002517 return false;
2518 }
2519 break;
2520 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002521 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002522 return false;
2523 }
2524
Geoff Lang2186c382016-10-14 10:54:54 -04002525 if (numParams)
2526 {
2527 // All queries return only one value
2528 *numParams = 1;
2529 }
2530
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002531 return true;
2532}
2533
2534bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2535{
2536 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002537 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002538 {
Jamie Madill437fa652016-05-03 15:13:24 -04002539 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002540 return false;
2541 }
2542
Geoff Lang2186c382016-10-14 10:54:54 -04002543 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002544}
2545
Geoff Lang2186c382016-10-14 10:54:54 -04002546bool ValidateGetQueryivRobustANGLE(Context *context,
2547 GLenum target,
2548 GLenum pname,
2549 GLsizei bufSize,
2550 GLsizei *length,
2551 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002552{
Geoff Lang2186c382016-10-14 10:54:54 -04002553 if (!ValidateRobustEntryPoint(context, bufSize))
2554 {
2555 return false;
2556 }
2557
2558 if (!ValidateGetQueryivBase(context, target, pname, length))
2559 {
2560 return false;
2561 }
2562
2563 if (!ValidateRobustBufferSize(context, bufSize, *length))
2564 {
2565 return false;
2566 }
2567
2568 return true;
2569}
2570
2571bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2572{
2573 if (numParams)
2574 {
2575 *numParams = 0;
2576 }
2577
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002578 Query *queryObject = context->getQuery(id, false, GL_NONE);
2579
2580 if (!queryObject)
2581 {
Jamie Madill437fa652016-05-03 15:13:24 -04002582 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002583 return false;
2584 }
2585
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002586 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002587 {
Jamie Madill437fa652016-05-03 15:13:24 -04002588 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002589 return false;
2590 }
2591
2592 switch (pname)
2593 {
2594 case GL_QUERY_RESULT_EXT:
2595 case GL_QUERY_RESULT_AVAILABLE_EXT:
2596 break;
2597
2598 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002599 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002600 return false;
2601 }
2602
Geoff Lang2186c382016-10-14 10:54:54 -04002603 if (numParams)
2604 {
2605 *numParams = 1;
2606 }
2607
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002608 return true;
2609}
2610
2611bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2612{
2613 if (!context->getExtensions().disjointTimerQuery)
2614 {
Jamie Madill437fa652016-05-03 15:13:24 -04002615 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002616 return false;
2617 }
Geoff Lang2186c382016-10-14 10:54:54 -04002618 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2619}
2620
2621bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2622 GLuint id,
2623 GLenum pname,
2624 GLsizei bufSize,
2625 GLsizei *length,
2626 GLint *params)
2627{
2628 if (!context->getExtensions().disjointTimerQuery)
2629 {
2630 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2631 return false;
2632 }
2633
2634 if (!ValidateRobustEntryPoint(context, bufSize))
2635 {
2636 return false;
2637 }
2638
2639 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2640 {
2641 return false;
2642 }
2643
2644 if (!ValidateRobustBufferSize(context, bufSize, *length))
2645 {
2646 return false;
2647 }
2648
2649 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002650}
2651
2652bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2653{
2654 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002655 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002656 {
Jamie Madill437fa652016-05-03 15:13:24 -04002657 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002658 return false;
2659 }
Geoff Lang2186c382016-10-14 10:54:54 -04002660 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2661}
2662
2663bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2664 GLuint id,
2665 GLenum pname,
2666 GLsizei bufSize,
2667 GLsizei *length,
2668 GLuint *params)
2669{
2670 if (!context->getExtensions().disjointTimerQuery &&
2671 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2672 {
2673 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2674 return false;
2675 }
2676
2677 if (!ValidateRobustEntryPoint(context, bufSize))
2678 {
2679 return false;
2680 }
2681
2682 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2683 {
2684 return false;
2685 }
2686
2687 if (!ValidateRobustBufferSize(context, bufSize, *length))
2688 {
2689 return false;
2690 }
2691
2692 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002693}
2694
2695bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2696{
2697 if (!context->getExtensions().disjointTimerQuery)
2698 {
Jamie Madill437fa652016-05-03 15:13:24 -04002699 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002700 return false;
2701 }
Geoff Lang2186c382016-10-14 10:54:54 -04002702 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2703}
2704
2705bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2706 GLuint id,
2707 GLenum pname,
2708 GLsizei bufSize,
2709 GLsizei *length,
2710 GLint64 *params)
2711{
2712 if (!context->getExtensions().disjointTimerQuery)
2713 {
2714 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2715 return false;
2716 }
2717
2718 if (!ValidateRobustEntryPoint(context, bufSize))
2719 {
2720 return false;
2721 }
2722
2723 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2724 {
2725 return false;
2726 }
2727
2728 if (!ValidateRobustBufferSize(context, bufSize, *length))
2729 {
2730 return false;
2731 }
2732
2733 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002734}
2735
2736bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2737{
2738 if (!context->getExtensions().disjointTimerQuery)
2739 {
Jamie Madill437fa652016-05-03 15:13:24 -04002740 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002741 return false;
2742 }
Geoff Lang2186c382016-10-14 10:54:54 -04002743 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2744}
2745
2746bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2747 GLuint id,
2748 GLenum pname,
2749 GLsizei bufSize,
2750 GLsizei *length,
2751 GLuint64 *params)
2752{
2753 if (!context->getExtensions().disjointTimerQuery)
2754 {
2755 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2756 return false;
2757 }
2758
2759 if (!ValidateRobustEntryPoint(context, bufSize))
2760 {
2761 return false;
2762 }
2763
2764 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2765 {
2766 return false;
2767 }
2768
2769 if (!ValidateRobustBufferSize(context, bufSize, *length))
2770 {
2771 return false;
2772 }
2773
2774 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002775}
2776
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002777bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002778 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002779 GLuint program,
2780 GLint location,
2781 GLsizei count)
2782{
2783 // Check for ES31 program uniform entry points
2784 if (context->getClientVersion() < Version(3, 1))
2785 {
2786 context->handleError(Error(GL_INVALID_OPERATION));
2787 return false;
2788 }
2789
2790 const LinkedUniform *uniform = nullptr;
2791 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002792 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2793 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002794}
2795
2796bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002797 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002798 GLuint program,
2799 GLint location,
2800 GLsizei count,
2801 GLboolean transpose)
2802{
2803 // Check for ES31 program uniform entry points
2804 if (context->getClientVersion() < Version(3, 1))
2805 {
2806 context->handleError(Error(GL_INVALID_OPERATION));
2807 return false;
2808 }
2809
2810 const LinkedUniform *uniform = nullptr;
2811 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002812 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2813 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002814}
2815
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002816bool ValidateUniform(gl::Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002817{
2818 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002819 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002820 {
Jamie Madill437fa652016-05-03 15:13:24 -04002821 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002822 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002823 }
2824
Jamie Madill62d31cb2015-09-11 13:25:51 -04002825 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002826 gl::Program *programObject = context->getGLState().getProgram();
2827 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2828 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002829}
2830
He Yunchaoced53ae2016-11-29 15:00:51 +08002831bool ValidateUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002832 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002833 GLint location,
2834 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002835 GLboolean transpose)
2836{
2837 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002838 int rows = VariableRowCount(valueType);
2839 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002840 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002841 {
Jamie Madill437fa652016-05-03 15:13:24 -04002842 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002843 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002844 }
2845
Martin Radev1be913c2016-07-11 17:59:16 +03002846 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002847 {
Jamie Madill437fa652016-05-03 15:13:24 -04002848 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002849 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002850 }
2851
Jamie Madill62d31cb2015-09-11 13:25:51 -04002852 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002853 gl::Program *programObject = context->getGLState().getProgram();
2854 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2855 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002856}
2857
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002858bool ValidateStateQuery(ValidationContext *context,
2859 GLenum pname,
2860 GLenum *nativeType,
2861 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002862{
2863 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2864 {
Jamie Madill437fa652016-05-03 15:13:24 -04002865 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002866 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002867 }
2868
Jamie Madill0af26e12015-03-05 19:54:33 -05002869 const Caps &caps = context->getCaps();
2870
Jamie Madill893ab082014-05-16 16:56:10 -04002871 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2872 {
2873 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2874
Jamie Madill0af26e12015-03-05 19:54:33 -05002875 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002876 {
Jamie Madill437fa652016-05-03 15:13:24 -04002877 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002878 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002879 }
2880 }
2881
2882 switch (pname)
2883 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002884 case GL_TEXTURE_BINDING_2D:
2885 case GL_TEXTURE_BINDING_CUBE_MAP:
2886 case GL_TEXTURE_BINDING_3D:
2887 case GL_TEXTURE_BINDING_2D_ARRAY:
2888 break;
2889 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2890 if (!context->getExtensions().eglStreamConsumerExternal &&
2891 !context->getExtensions().eglImageExternal)
2892 {
2893 context->handleError(Error(GL_INVALID_ENUM,
2894 "Neither NV_EGL_stream_consumer_external nor "
2895 "GL_OES_EGL_image_external extensions enabled"));
2896 return false;
2897 }
2898 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002899
He Yunchaoced53ae2016-11-29 15:00:51 +08002900 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2901 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002902 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002903 if (context->getGLState().getReadFramebuffer()->checkStatus(
2904 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002905 {
Jamie Madill437fa652016-05-03 15:13:24 -04002906 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002907 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002908 }
2909
Jamie Madill51f40ec2016-06-15 14:06:00 -04002910 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2911 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002912
2913 if (framebuffer->getReadBufferState() == GL_NONE)
2914 {
2915 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2916 return false;
2917 }
2918
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002919 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002920 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002921 {
Jamie Madill437fa652016-05-03 15:13:24 -04002922 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002923 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002924 }
2925 }
2926 break;
2927
He Yunchaoced53ae2016-11-29 15:00:51 +08002928 default:
2929 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002930 }
2931
2932 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002933 if (*numParams == 0)
2934 {
2935 return false;
2936 }
2937
2938 return true;
2939}
2940
2941bool ValidateRobustStateQuery(ValidationContext *context,
2942 GLenum pname,
2943 GLsizei bufSize,
2944 GLenum *nativeType,
2945 unsigned int *numParams)
2946{
2947 if (!ValidateRobustEntryPoint(context, bufSize))
2948 {
2949 return false;
2950 }
2951
2952 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2953 {
2954 return false;
2955 }
2956
2957 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002958 {
2959 return false;
2960 }
2961
2962 return true;
2963}
2964
Jamie Madillc29968b2016-01-20 11:17:23 -05002965bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2966 GLenum target,
2967 GLint level,
2968 GLenum internalformat,
2969 bool isSubImage,
2970 GLint xoffset,
2971 GLint yoffset,
2972 GLint zoffset,
2973 GLint x,
2974 GLint y,
2975 GLsizei width,
2976 GLsizei height,
2977 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002978 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002979{
Jamie Madill560a8d82014-05-21 13:06:20 -04002980 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2981 {
Jamie Madill437fa652016-05-03 15:13:24 -04002982 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002983 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002984 }
2985
He Yunchaoced53ae2016-11-29 15:00:51 +08002986 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2987 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002988 {
Jamie Madill437fa652016-05-03 15:13:24 -04002989 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002990 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002991 }
2992
2993 if (border != 0)
2994 {
Jamie Madill437fa652016-05-03 15:13:24 -04002995 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002996 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002997 }
2998
2999 if (!ValidMipLevel(context, target, level))
3000 {
Jamie Madill437fa652016-05-03 15:13:24 -04003001 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003002 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003003 }
3004
Jamie Madill51f40ec2016-06-15 14:06:00 -04003005 const auto &state = context->getGLState();
3006 auto readFramebuffer = state.getReadFramebuffer();
3007 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003008 {
Jamie Madill437fa652016-05-03 15:13:24 -04003009 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003010 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003011 }
3012
Jamie Madill51f40ec2016-06-15 14:06:00 -04003013 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003014 {
Jamie Madill437fa652016-05-03 15:13:24 -04003015 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003016 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003017 }
3018
Martin Radev138064f2016-07-15 12:03:41 +03003019 if (readFramebuffer->getReadBufferState() == GL_NONE)
3020 {
3021 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3022 return false;
3023 }
3024
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003025 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3026 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003027 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003028 // situation is an application error that would lead to a crash in ANGLE.
3029 if (readFramebuffer->getReadColorbuffer() == nullptr)
3030 {
3031 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3032 return false;
3033 }
3034
Geoff Langaae65a42014-05-26 12:43:44 -04003035 const gl::Caps &caps = context->getCaps();
3036
Geoff Langaae65a42014-05-26 12:43:44 -04003037 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003038 switch (target)
3039 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003040 case GL_TEXTURE_2D:
3041 maxDimension = caps.max2DTextureSize;
3042 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003043
He Yunchaoced53ae2016-11-29 15:00:51 +08003044 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3045 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3046 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3047 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3048 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3049 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3050 maxDimension = caps.maxCubeMapTextureSize;
3051 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003052
He Yunchaoced53ae2016-11-29 15:00:51 +08003053 case GL_TEXTURE_2D_ARRAY:
3054 maxDimension = caps.max2DTextureSize;
3055 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003056
He Yunchaoced53ae2016-11-29 15:00:51 +08003057 case GL_TEXTURE_3D:
3058 maxDimension = caps.max3DTextureSize;
3059 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003060
He Yunchaoced53ae2016-11-29 15:00:51 +08003061 default:
3062 context->handleError(Error(GL_INVALID_ENUM));
3063 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003064 }
3065
Jamie Madillc29968b2016-01-20 11:17:23 -05003066 gl::Texture *texture =
3067 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003068 if (!texture)
3069 {
Jamie Madill437fa652016-05-03 15:13:24 -04003070 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003071 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003072 }
3073
Geoff Lang69cce582015-09-17 13:20:36 -04003074 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003075 {
Jamie Madill437fa652016-05-03 15:13:24 -04003076 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003077 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003078 }
3079
Geoff Lang5d601382014-07-22 15:14:06 -04003080 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3081
3082 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003083 {
Jamie Madill437fa652016-05-03 15:13:24 -04003084 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003085 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003086 }
3087
Geoff Langa9be0dc2014-12-17 12:34:40 -05003088 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003089 {
Jamie Madill437fa652016-05-03 15:13:24 -04003090 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003091 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003092 }
3093
3094 if (isSubImage)
3095 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003096 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3097 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3098 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003099 {
Jamie Madill437fa652016-05-03 15:13:24 -04003100 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003101 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003102 }
3103 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003104 else
3105 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003106 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003107 {
Jamie Madill437fa652016-05-03 15:13:24 -04003108 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003109 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003110 }
3111
Geoff Langeb66a6e2016-10-31 13:06:12 -04003112 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003113 {
Jamie Madill437fa652016-05-03 15:13:24 -04003114 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003115 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003116 }
3117
3118 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003119 if (static_cast<int>(width) > maxLevelDimension ||
3120 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003121 {
Jamie Madill437fa652016-05-03 15:13:24 -04003122 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003123 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003124 }
3125 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003126
Jamie Madill0c8abca2016-07-22 20:21:26 -04003127 if (textureFormatOut)
3128 {
3129 *textureFormatOut = texture->getFormat(target, level);
3130 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003131
3132 // Detect texture copying feedback loops for WebGL.
3133 if (context->getExtensions().webglCompatibility)
3134 {
3135 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level))
3136 {
3137 context->handleError(Error(GL_INVALID_OPERATION,
3138 "Texture copying feedback loop formed between Framebuffer "
3139 "and specified Texture level."));
3140 return false;
3141 }
3142 }
3143
Jamie Madill560a8d82014-05-21 13:06:20 -04003144 return true;
3145}
3146
Jiajia Qind9671222016-11-29 16:30:31 +08003147bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003148{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003149 switch (mode)
3150 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003151 case GL_POINTS:
3152 case GL_LINES:
3153 case GL_LINE_LOOP:
3154 case GL_LINE_STRIP:
3155 case GL_TRIANGLES:
3156 case GL_TRIANGLE_STRIP:
3157 case GL_TRIANGLE_FAN:
3158 break;
3159 default:
3160 context->handleError(Error(GL_INVALID_ENUM));
3161 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003162 }
3163
Jamie Madill250d33f2014-06-06 17:09:03 -04003164 if (count < 0)
3165 {
Jamie Madill437fa652016-05-03 15:13:24 -04003166 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003167 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003168 }
3169
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003170 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003171
Jamie Madill250d33f2014-06-06 17:09:03 -04003172 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003173 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003174 {
Jamie Madill437fa652016-05-03 15:13:24 -04003175 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003176 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003177 }
3178
Jamie Madillcbcde722017-01-06 14:50:00 -05003179 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3180 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003181 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003182 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3183 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003184 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003185 const FramebufferAttachment *dsAttachment =
3186 framebuffer->getStencilOrDepthStencilAttachment();
3187 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003188 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003189 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003190
3191 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3192 bool differentWritemasks =
3193 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3194 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3195 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3196 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3197
3198 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003199 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003200 if (!context->getExtensions().webglCompatibility)
3201 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003202 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3203 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003204 }
Jamie Madill437fa652016-05-03 15:13:24 -04003205 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003206 return false;
3207 }
Jamie Madillac528012014-06-20 13:21:23 -04003208 }
3209
Jamie Madill51f40ec2016-06-15 14:06:00 -04003210 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003211 {
Jamie Madill437fa652016-05-03 15:13:24 -04003212 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003213 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003214 }
3215
Geoff Lang7dd2e102014-11-10 15:19:26 -05003216 gl::Program *program = state.getProgram();
3217 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003218 {
Jamie Madill437fa652016-05-03 15:13:24 -04003219 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003220 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003221 }
3222
Geoff Lang7dd2e102014-11-10 15:19:26 -05003223 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003224 {
Jamie Madill437fa652016-05-03 15:13:24 -04003225 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003226 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003227 }
3228
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003229 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003230 for (unsigned int uniformBlockIndex = 0;
3231 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003232 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003233 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003234 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003235 const OffsetBindingPointer<Buffer> &uniformBuffer =
3236 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003237
Geoff Lang5d124a62015-09-15 13:03:27 -04003238 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003239 {
3240 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003241 context->handleError(
3242 Error(GL_INVALID_OPERATION,
3243 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003244 return false;
3245 }
3246
Geoff Lang5d124a62015-09-15 13:03:27 -04003247 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003248 if (uniformBufferSize == 0)
3249 {
3250 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003251 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003252 }
3253
Jamie Madill62d31cb2015-09-11 13:25:51 -04003254 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003255 {
3256 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003257 context->handleError(
3258 Error(GL_INVALID_OPERATION,
3259 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003260 return false;
3261 }
3262 }
3263
Jamie Madilla4595b82017-01-11 17:36:34 -05003264 // Detect rendering feedback loops for WebGL.
3265 if (context->getExtensions().webglCompatibility)
3266 {
3267 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3268 {
3269 context->handleError(
3270 Error(GL_INVALID_OPERATION,
3271 "Rendering feedback loop formed between Framebuffer and active Texture."));
3272 return false;
3273 }
3274 }
3275
Jamie Madill250d33f2014-06-06 17:09:03 -04003276 // No-op if zero count
3277 return (count > 0);
3278}
3279
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003280bool ValidateDrawArrays(ValidationContext *context,
3281 GLenum mode,
3282 GLint first,
3283 GLsizei count,
3284 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003285{
Jamie Madillfd716582014-06-06 17:09:04 -04003286 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003287 {
Jamie Madill437fa652016-05-03 15:13:24 -04003288 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003289 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003290 }
3291
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003292 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003293 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003294 if (curTransformFeedback && curTransformFeedback->isActive() &&
3295 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003296 {
3297 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003298 // that does not match the current transform feedback object's draw mode (if transform
3299 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003300 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003301 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003302 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003303 }
3304
Jiajia Qind9671222016-11-29 16:30:31 +08003305 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003306 {
3307 return false;
3308 }
3309
Corentin Wallez71168a02016-12-19 15:11:18 -08003310 // Check the computation of maxVertex doesn't overflow.
3311 // - first < 0 or count < 0 have been checked as an error condition
3312 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3313 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3314 ASSERT(count > 0 && first >= 0);
3315 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3316 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003317 {
3318 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3319 return false;
3320 }
3321
Corentin Wallez71168a02016-12-19 15:11:18 -08003322 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003323 {
3324 return false;
3325 }
3326
3327 return true;
3328}
3329
He Yunchaoced53ae2016-11-29 15:00:51 +08003330bool ValidateDrawArraysInstanced(Context *context,
3331 GLenum mode,
3332 GLint first,
3333 GLsizei count,
3334 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003335{
3336 if (primcount < 0)
3337 {
Jamie Madill437fa652016-05-03 15:13:24 -04003338 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003339 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003340 }
3341
Jamie Madill2b976812014-08-25 15:47:49 -04003342 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003343 {
3344 return false;
3345 }
3346
3347 // No-op if zero primitive count
3348 return (primcount > 0);
3349}
3350
Geoff Lang87a93302014-09-16 13:29:43 -04003351static bool ValidateDrawInstancedANGLE(Context *context)
3352{
3353 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003354 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003355
Geoff Lang7dd2e102014-11-10 15:19:26 -05003356 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003357
3358 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003359 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003360 {
3361 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003362 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003363 {
3364 return true;
3365 }
3366 }
3367
Jamie Madill437fa652016-05-03 15:13:24 -04003368 context->handleError(Error(GL_INVALID_OPERATION,
3369 "ANGLE_instanced_arrays requires that at least one active attribute"
3370 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003371 return false;
3372}
3373
He Yunchaoced53ae2016-11-29 15:00:51 +08003374bool ValidateDrawArraysInstancedANGLE(Context *context,
3375 GLenum mode,
3376 GLint first,
3377 GLsizei count,
3378 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003379{
3380 if (!ValidateDrawInstancedANGLE(context))
3381 {
3382 return false;
3383 }
3384
3385 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3386}
3387
Jiajia Qind9671222016-11-29 16:30:31 +08003388bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003389{
Jamie Madill250d33f2014-06-06 17:09:03 -04003390 switch (type)
3391 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003392 case GL_UNSIGNED_BYTE:
3393 case GL_UNSIGNED_SHORT:
3394 break;
3395 case GL_UNSIGNED_INT:
3396 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3397 {
3398 context->handleError(Error(GL_INVALID_ENUM));
3399 return false;
3400 }
3401 break;
3402 default:
3403 context->handleError(Error(GL_INVALID_ENUM));
3404 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003405 }
3406
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003407 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003408
3409 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003410 if (curTransformFeedback && curTransformFeedback->isActive() &&
3411 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003412 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003413 // It is an invalid operation to call DrawElements, DrawRangeElements or
3414 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003415 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003416 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003417 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003418 }
3419
Jiajia Qind9671222016-11-29 16:30:31 +08003420 return true;
3421}
3422
3423bool ValidateDrawElements(ValidationContext *context,
3424 GLenum mode,
3425 GLsizei count,
3426 GLenum type,
3427 const GLvoid *indices,
3428 GLsizei primcount,
3429 IndexRange *indexRangeOut)
3430{
3431 if (!ValidateDrawElementsBase(context, type))
3432 return false;
3433
3434 const State &state = context->getGLState();
3435
Jamie Madill250d33f2014-06-06 17:09:03 -04003436 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003437 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003438 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003439 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04003440 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003441 }
3442
He Yunchaoced53ae2016-11-29 15:00:51 +08003443 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003444 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003445
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003446 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3447
3448 if (context->getExtensions().webglCompatibility)
3449 {
3450 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3451 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3452 {
3453 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3454 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3455 // data type passed to the call, or an INVALID_OPERATION error is generated.
3456 context->handleError(Error(GL_INVALID_OPERATION,
3457 "indices must be a multiple of the element type size."));
3458 return false;
3459 }
3460 if (!elementArrayBuffer && count > 0)
3461 {
3462 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3463 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3464 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3465 context->handleError(Error(GL_INVALID_OPERATION,
3466 "There is no element array buffer bound and count > 0."));
3467 return false;
3468 }
3469 }
3470
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003471 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003472 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003473 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003474 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003475 GLint64 offset = reinterpret_cast<GLint64>(indices);
3476 GLint64 byteCount =
3477 static_cast<GLint64>(typeBytes) * static_cast<GLint64>(count) + offset;
3478
3479 // check for integer overflows
3480 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeBytes) ||
3481 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3482 {
3483 context->handleError(Error(GL_OUT_OF_MEMORY, "Integer overflow."));
3484 return false;
3485 }
3486
3487 // Check for reading past the end of the bound buffer object
3488 if (byteCount > elementArrayBuffer->getSize())
3489 {
3490 context->handleError(
3491 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
3492 return false;
3493 }
3494 }
3495 else if (!indices)
3496 {
3497 // This is an application error that would normally result in a crash,
3498 // but we catch it and return an error
3499 context->handleError(
3500 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003501 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003502 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003503 }
3504
Jiajia Qind9671222016-11-29 16:30:31 +08003505 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003506 {
3507 return false;
3508 }
3509
Jamie Madill2b976812014-08-25 15:47:49 -04003510 // Use max index to validate if our vertex buffers are large enough for the pull.
3511 // TODO: offer fast path, with disabled index validation.
3512 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3513 if (elementArrayBuffer)
3514 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003515 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003516 Error error =
3517 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3518 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003519 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003520 {
Jamie Madill437fa652016-05-03 15:13:24 -04003521 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003522 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003523 }
3524 }
3525 else
3526 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003527 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003528 }
3529
Jamie Madille79b1e12015-11-04 16:36:37 -05003530 // If we use an index greater than our maximum supported index range, return an error.
3531 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3532 // return an error if possible here.
3533 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3534 {
Jamie Madill437fa652016-05-03 15:13:24 -04003535 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003536 return false;
3537 }
3538
Corentin Wallez92db6942016-12-09 13:10:36 -05003539 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3540 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003541 {
3542 return false;
3543 }
3544
Geoff Lang3edfe032015-09-04 16:38:24 -04003545 // No op if there are no real indices in the index data (all are primitive restart).
3546 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003547}
3548
Geoff Langb1196682014-07-23 13:47:29 -04003549bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003550 GLenum mode,
3551 GLsizei count,
3552 GLenum type,
3553 const GLvoid *indices,
3554 GLsizei primcount,
3555 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003556{
3557 if (primcount < 0)
3558 {
Jamie Madill437fa652016-05-03 15:13:24 -04003559 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003560 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003561 }
3562
Jamie Madill2b976812014-08-25 15:47:49 -04003563 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003564 {
3565 return false;
3566 }
3567
3568 // No-op zero primitive count
3569 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003570}
3571
Geoff Lang3edfe032015-09-04 16:38:24 -04003572bool ValidateDrawElementsInstancedANGLE(Context *context,
3573 GLenum mode,
3574 GLsizei count,
3575 GLenum type,
3576 const GLvoid *indices,
3577 GLsizei primcount,
3578 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003579{
3580 if (!ValidateDrawInstancedANGLE(context))
3581 {
3582 return false;
3583 }
3584
He Yunchaoced53ae2016-11-29 15:00:51 +08003585 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3586 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003587}
3588
He Yunchaoced53ae2016-11-29 15:00:51 +08003589bool ValidateFramebufferTextureBase(Context *context,
3590 GLenum target,
3591 GLenum attachment,
3592 GLuint texture,
3593 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003594{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003595 if (!ValidFramebufferTarget(target))
3596 {
Jamie Madill437fa652016-05-03 15:13:24 -04003597 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003598 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003599 }
3600
3601 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003602 {
3603 return false;
3604 }
3605
Jamie Madill55ec3b12014-07-03 10:38:57 -04003606 if (texture != 0)
3607 {
3608 gl::Texture *tex = context->getTexture(texture);
3609
3610 if (tex == NULL)
3611 {
Jamie Madill437fa652016-05-03 15:13:24 -04003612 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003613 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003614 }
3615
3616 if (level < 0)
3617 {
Jamie Madill437fa652016-05-03 15:13:24 -04003618 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003619 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003620 }
3621 }
3622
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003623 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003624 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003625
Jamie Madill84115c92015-04-23 15:00:07 -04003626 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003627 {
Jamie Madill437fa652016-05-03 15:13:24 -04003628 context->handleError(
3629 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003630 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003631 }
3632
3633 return true;
3634}
3635
He Yunchaoced53ae2016-11-29 15:00:51 +08003636bool ValidateFramebufferTexture2D(Context *context,
3637 GLenum target,
3638 GLenum attachment,
3639 GLenum textarget,
3640 GLuint texture,
3641 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003642{
He Yunchaoced53ae2016-11-29 15:00:51 +08003643 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3644 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003645 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3646 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003647 {
Jamie Madill437fa652016-05-03 15:13:24 -04003648 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003649 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003650 }
3651
3652 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003653 {
3654 return false;
3655 }
3656
Jamie Madill55ec3b12014-07-03 10:38:57 -04003657 if (texture != 0)
3658 {
3659 gl::Texture *tex = context->getTexture(texture);
3660 ASSERT(tex);
3661
Jamie Madill2a6564e2014-07-11 09:53:19 -04003662 const gl::Caps &caps = context->getCaps();
3663
Jamie Madill55ec3b12014-07-03 10:38:57 -04003664 switch (textarget)
3665 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003666 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003667 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003668 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003669 {
Jamie Madill437fa652016-05-03 15:13:24 -04003670 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003671 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003672 }
3673 if (tex->getTarget() != GL_TEXTURE_2D)
3674 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003675 context->handleError(Error(GL_INVALID_OPERATION,
3676 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003677 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003678 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003679 }
3680 break;
3681
He Yunchaoced53ae2016-11-29 15:00:51 +08003682 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3683 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3684 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3685 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3686 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3687 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003688 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003689 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003690 {
Jamie Madill437fa652016-05-03 15:13:24 -04003691 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003692 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003693 }
3694 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3695 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003696 context->handleError(Error(GL_INVALID_OPERATION,
3697 "Textarget must match the texture target type."));
3698 return false;
3699 }
3700 }
3701 break;
3702
3703 case GL_TEXTURE_2D_MULTISAMPLE:
3704 {
3705 if (context->getClientVersion() < ES_3_1)
3706 {
3707 context->handleError(Error(GL_INVALID_OPERATION,
3708 "Texture target requires at least OpenGL ES 3.1."));
3709 return false;
3710 }
3711
3712 if (level != 0)
3713 {
3714 context->handleError(
3715 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
3716 return false;
3717 }
3718 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
3719 {
3720 context->handleError(Error(GL_INVALID_OPERATION,
3721 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003722 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003723 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003724 }
3725 break;
3726
He Yunchaoced53ae2016-11-29 15:00:51 +08003727 default:
3728 context->handleError(Error(GL_INVALID_ENUM));
3729 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003730 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003731
Jamie Madilla3944d42016-07-22 22:13:26 -04003732 const Format &format = tex->getFormat(textarget, level);
3733 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003734 {
Jamie Madill437fa652016-05-03 15:13:24 -04003735 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003736 return false;
3737 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003738 }
3739
Jamie Madill570f7c82014-07-03 10:38:54 -04003740 return true;
3741}
3742
Geoff Langb1196682014-07-23 13:47:29 -04003743bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003744{
3745 if (program == 0)
3746 {
Jamie Madill437fa652016-05-03 15:13:24 -04003747 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003748 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003749 }
3750
Dian Xiang769769a2015-09-09 15:20:08 -07003751 gl::Program *programObject = GetValidProgram(context, program);
3752 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003753 {
3754 return false;
3755 }
3756
Jamie Madill0063c512014-08-25 15:47:53 -04003757 if (!programObject || !programObject->isLinked())
3758 {
Jamie Madill437fa652016-05-03 15:13:24 -04003759 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003760 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003761 }
3762
Geoff Lang7dd2e102014-11-10 15:19:26 -05003763 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003764 {
Jamie Madill437fa652016-05-03 15:13:24 -04003765 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003766 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003767 }
3768
Jamie Madill0063c512014-08-25 15:47:53 -04003769 return true;
3770}
3771
He Yunchaoced53ae2016-11-29 15:00:51 +08003772bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003773{
3774 return ValidateGetUniformBase(context, program, location);
3775}
3776
He Yunchaoced53ae2016-11-29 15:00:51 +08003777bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003778{
Jamie Madill78f41802014-08-25 15:47:55 -04003779 return ValidateGetUniformBase(context, program, location);
3780}
3781
Geoff Langf41d0ee2016-10-07 13:04:23 -04003782static bool ValidateSizedGetUniform(Context *context,
3783 GLuint program,
3784 GLint location,
3785 GLsizei bufSize,
3786 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003787{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003788 if (length)
3789 {
3790 *length = 0;
3791 }
3792
Jamie Madill78f41802014-08-25 15:47:55 -04003793 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003794 {
Jamie Madill78f41802014-08-25 15:47:55 -04003795 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003796 }
3797
Geoff Langf41d0ee2016-10-07 13:04:23 -04003798 if (bufSize < 0)
3799 {
3800 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3801 return false;
3802 }
3803
Jamie Madilla502c742014-08-28 17:19:13 -04003804 gl::Program *programObject = context->getProgram(program);
3805 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003806
Jamie Madill78f41802014-08-25 15:47:55 -04003807 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003808 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003809 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003810 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003811 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003812 context->handleError(
3813 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003814 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003815 }
3816
Geoff Langf41d0ee2016-10-07 13:04:23 -04003817 if (length)
3818 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003819 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003820 }
3821
Jamie Madill0063c512014-08-25 15:47:53 -04003822 return true;
3823}
3824
He Yunchaoced53ae2016-11-29 15:00:51 +08003825bool ValidateGetnUniformfvEXT(Context *context,
3826 GLuint program,
3827 GLint location,
3828 GLsizei bufSize,
3829 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003830{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003831 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003832}
3833
He Yunchaoced53ae2016-11-29 15:00:51 +08003834bool ValidateGetnUniformivEXT(Context *context,
3835 GLuint program,
3836 GLint location,
3837 GLsizei bufSize,
3838 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003839{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003840 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3841}
3842
3843bool ValidateGetUniformfvRobustANGLE(Context *context,
3844 GLuint program,
3845 GLint location,
3846 GLsizei bufSize,
3847 GLsizei *length,
3848 GLfloat *params)
3849{
3850 if (!ValidateRobustEntryPoint(context, bufSize))
3851 {
3852 return false;
3853 }
3854
3855 // bufSize is validated in ValidateSizedGetUniform
3856 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3857}
3858
3859bool ValidateGetUniformivRobustANGLE(Context *context,
3860 GLuint program,
3861 GLint location,
3862 GLsizei bufSize,
3863 GLsizei *length,
3864 GLint *params)
3865{
3866 if (!ValidateRobustEntryPoint(context, bufSize))
3867 {
3868 return false;
3869 }
3870
3871 // bufSize is validated in ValidateSizedGetUniform
3872 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3873}
3874
3875bool ValidateGetUniformuivRobustANGLE(Context *context,
3876 GLuint program,
3877 GLint location,
3878 GLsizei bufSize,
3879 GLsizei *length,
3880 GLuint *params)
3881{
3882 if (!ValidateRobustEntryPoint(context, bufSize))
3883 {
3884 return false;
3885 }
3886
3887 if (context->getClientMajorVersion() < 3)
3888 {
3889 context->handleError(
3890 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3891 return false;
3892 }
3893
3894 // bufSize is validated in ValidateSizedGetUniform
3895 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003896}
3897
He Yunchaoced53ae2016-11-29 15:00:51 +08003898bool ValidateDiscardFramebufferBase(Context *context,
3899 GLenum target,
3900 GLsizei numAttachments,
3901 const GLenum *attachments,
3902 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003903{
3904 if (numAttachments < 0)
3905 {
Jamie Madill437fa652016-05-03 15:13:24 -04003906 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003907 return false;
3908 }
3909
3910 for (GLsizei i = 0; i < numAttachments; ++i)
3911 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003912 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003913 {
3914 if (defaultFramebuffer)
3915 {
Jamie Madill437fa652016-05-03 15:13:24 -04003916 context->handleError(Error(
3917 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003918 return false;
3919 }
3920
3921 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3922 {
Jamie Madill437fa652016-05-03 15:13:24 -04003923 context->handleError(Error(GL_INVALID_OPERATION,
3924 "Requested color attachment is greater than the maximum "
3925 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003926 return false;
3927 }
3928 }
3929 else
3930 {
3931 switch (attachments[i])
3932 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003933 case GL_DEPTH_ATTACHMENT:
3934 case GL_STENCIL_ATTACHMENT:
3935 case GL_DEPTH_STENCIL_ATTACHMENT:
3936 if (defaultFramebuffer)
3937 {
3938 context->handleError(
3939 Error(GL_INVALID_ENUM,
3940 "Invalid attachment when the default framebuffer is bound"));
3941 return false;
3942 }
3943 break;
3944 case GL_COLOR:
3945 case GL_DEPTH:
3946 case GL_STENCIL:
3947 if (!defaultFramebuffer)
3948 {
3949 context->handleError(
3950 Error(GL_INVALID_ENUM,
3951 "Invalid attachment when the default framebuffer is not bound"));
3952 return false;
3953 }
3954 break;
3955 default:
3956 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003957 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003958 }
3959 }
3960 }
3961
3962 return true;
3963}
3964
Austin Kinross6ee1e782015-05-29 17:05:37 -07003965bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3966{
3967 // Note that debug marker calls must not set error state
3968
3969 if (length < 0)
3970 {
3971 return false;
3972 }
3973
3974 if (marker == nullptr)
3975 {
3976 return false;
3977 }
3978
3979 return true;
3980}
3981
3982bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3983{
3984 // Note that debug marker calls must not set error state
3985
3986 if (length < 0)
3987 {
3988 return false;
3989 }
3990
3991 if (length > 0 && marker == nullptr)
3992 {
3993 return false;
3994 }
3995
3996 return true;
3997}
3998
Geoff Langdcab33b2015-07-21 13:03:16 -04003999bool ValidateEGLImageTargetTexture2DOES(Context *context,
4000 egl::Display *display,
4001 GLenum target,
4002 egl::Image *image)
4003{
Geoff Langa8406172015-07-21 16:53:39 -04004004 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4005 {
Jamie Madill437fa652016-05-03 15:13:24 -04004006 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004007 return false;
4008 }
4009
4010 switch (target)
4011 {
4012 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004013 if (!context->getExtensions().eglImage)
4014 {
4015 context->handleError(Error(
4016 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4017 }
4018 break;
4019
4020 case GL_TEXTURE_EXTERNAL_OES:
4021 if (!context->getExtensions().eglImageExternal)
4022 {
4023 context->handleError(Error(
4024 GL_INVALID_ENUM,
4025 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4026 }
Geoff Langa8406172015-07-21 16:53:39 -04004027 break;
4028
4029 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004030 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004031 return false;
4032 }
4033
4034 if (!display->isValidImage(image))
4035 {
Jamie Madill437fa652016-05-03 15:13:24 -04004036 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004037 return false;
4038 }
4039
4040 if (image->getSamples() > 0)
4041 {
Jamie Madill437fa652016-05-03 15:13:24 -04004042 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004043 "cannot create a 2D texture from a multisampled EGL image."));
4044 return false;
4045 }
4046
Jamie Madilla3944d42016-07-22 22:13:26 -04004047 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004048 if (!textureCaps.texturable)
4049 {
Jamie Madill437fa652016-05-03 15:13:24 -04004050 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004051 "EGL image internal format is not supported as a texture."));
4052 return false;
4053 }
4054
Geoff Langdcab33b2015-07-21 13:03:16 -04004055 return true;
4056}
4057
4058bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4059 egl::Display *display,
4060 GLenum target,
4061 egl::Image *image)
4062{
Geoff Langa8406172015-07-21 16:53:39 -04004063 if (!context->getExtensions().eglImage)
4064 {
Jamie Madill437fa652016-05-03 15:13:24 -04004065 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004066 return false;
4067 }
4068
4069 switch (target)
4070 {
4071 case GL_RENDERBUFFER:
4072 break;
4073
4074 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004075 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004076 return false;
4077 }
4078
4079 if (!display->isValidImage(image))
4080 {
Jamie Madill437fa652016-05-03 15:13:24 -04004081 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004082 return false;
4083 }
4084
Jamie Madilla3944d42016-07-22 22:13:26 -04004085 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004086 if (!textureCaps.renderable)
4087 {
Jamie Madill437fa652016-05-03 15:13:24 -04004088 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004089 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4090 return false;
4091 }
4092
Geoff Langdcab33b2015-07-21 13:03:16 -04004093 return true;
4094}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004095
4096bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4097{
Geoff Lang36167ab2015-12-07 10:27:14 -05004098 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004099 {
4100 // The default VAO should always exist
4101 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004102 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004103 return false;
4104 }
4105
4106 return true;
4107}
4108
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004109bool ValidateLinkProgram(Context *context, GLuint program)
4110{
4111 if (context->hasActiveTransformFeedback(program))
4112 {
4113 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004114 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004115 "Cannot link program while program is associated with an active "
4116 "transform feedback object."));
4117 return false;
4118 }
4119 return true;
4120}
4121
Geoff Langc5629752015-12-07 16:29:04 -05004122bool ValidateProgramBinaryBase(Context *context,
4123 GLuint program,
4124 GLenum binaryFormat,
4125 const void *binary,
4126 GLint length)
4127{
4128 Program *programObject = GetValidProgram(context, program);
4129 if (programObject == nullptr)
4130 {
4131 return false;
4132 }
4133
4134 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4135 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4136 programBinaryFormats.end())
4137 {
Jamie Madill437fa652016-05-03 15:13:24 -04004138 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004139 return false;
4140 }
4141
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004142 if (context->hasActiveTransformFeedback(program))
4143 {
4144 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004145 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004146 "Cannot change program binary while program is associated with "
4147 "an active transform feedback object."));
4148 return false;
4149 }
4150
Geoff Langc5629752015-12-07 16:29:04 -05004151 return true;
4152}
4153
4154bool ValidateGetProgramBinaryBase(Context *context,
4155 GLuint program,
4156 GLsizei bufSize,
4157 GLsizei *length,
4158 GLenum *binaryFormat,
4159 void *binary)
4160{
4161 Program *programObject = GetValidProgram(context, program);
4162 if (programObject == nullptr)
4163 {
4164 return false;
4165 }
4166
4167 if (!programObject->isLinked())
4168 {
Jamie Madill437fa652016-05-03 15:13:24 -04004169 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004170 return false;
4171 }
4172
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004173 if (context->getCaps().programBinaryFormats.empty())
4174 {
4175 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4176 return false;
4177 }
4178
Geoff Langc5629752015-12-07 16:29:04 -05004179 return true;
4180}
Jamie Madillc29968b2016-01-20 11:17:23 -05004181
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004182bool ValidateUseProgram(Context *context, GLuint program)
4183{
4184 if (program != 0)
4185 {
4186 Program *programObject = context->getProgram(program);
4187 if (!programObject)
4188 {
4189 // ES 3.1.0 section 7.3 page 72
4190 if (context->getShader(program))
4191 {
Jamie Madill437fa652016-05-03 15:13:24 -04004192 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004193 Error(GL_INVALID_OPERATION,
4194 "Attempted to use a single shader instead of a shader program."));
4195 return false;
4196 }
4197 else
4198 {
Jamie Madill437fa652016-05-03 15:13:24 -04004199 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004200 return false;
4201 }
4202 }
4203 if (!programObject->isLinked())
4204 {
Jamie Madill437fa652016-05-03 15:13:24 -04004205 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004206 return false;
4207 }
4208 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004209 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004210 {
4211 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004212 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004213 Error(GL_INVALID_OPERATION,
4214 "Cannot change active program while transform feedback is unpaused."));
4215 return false;
4216 }
4217
4218 return true;
4219}
4220
Jamie Madillc29968b2016-01-20 11:17:23 -05004221bool ValidateCopyTexImage2D(ValidationContext *context,
4222 GLenum target,
4223 GLint level,
4224 GLenum internalformat,
4225 GLint x,
4226 GLint y,
4227 GLsizei width,
4228 GLsizei height,
4229 GLint border)
4230{
Martin Radev1be913c2016-07-11 17:59:16 +03004231 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004232 {
4233 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4234 0, x, y, width, height, border);
4235 }
4236
Martin Radev1be913c2016-07-11 17:59:16 +03004237 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004238 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4239 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004240}
Jamie Madillc29968b2016-01-20 11:17:23 -05004241
4242bool ValidateFramebufferRenderbuffer(Context *context,
4243 GLenum target,
4244 GLenum attachment,
4245 GLenum renderbuffertarget,
4246 GLuint renderbuffer)
4247{
4248 if (!ValidFramebufferTarget(target) ||
4249 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4250 {
Jamie Madill437fa652016-05-03 15:13:24 -04004251 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004252 return false;
4253 }
4254
4255 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4256 renderbuffertarget, renderbuffer);
4257}
4258
4259bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4260{
4261 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4262 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4263 {
Jamie Madill437fa652016-05-03 15:13:24 -04004264 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004265 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4266 return false;
4267 }
4268
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004269 ASSERT(context->getGLState().getDrawFramebuffer());
4270 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004271 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4272
4273 // This should come first before the check for the default frame buffer
4274 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4275 // rather than INVALID_OPERATION
4276 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4277 {
4278 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4279
4280 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004281 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4282 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004283 {
4284 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004285 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4286 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4287 // 3.1 is still a bit ambiguous about the error, but future specs are
4288 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004289 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004290 return false;
4291 }
4292 else if (bufs[colorAttachment] >= maxColorAttachment)
4293 {
Jamie Madill437fa652016-05-03 15:13:24 -04004294 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004295 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004296 return false;
4297 }
4298 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4299 frameBufferId != 0)
4300 {
4301 // INVALID_OPERATION-GL is bound to buffer and ith argument
4302 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004303 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004304 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4305 return false;
4306 }
4307 }
4308
4309 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4310 // and n is not 1 or bufs is bound to value other than BACK and NONE
4311 if (frameBufferId == 0)
4312 {
4313 if (n != 1)
4314 {
Jamie Madill437fa652016-05-03 15:13:24 -04004315 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004316 "n must be 1 when GL is bound to the default framebuffer"));
4317 return false;
4318 }
4319
4320 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4321 {
Jamie Madill437fa652016-05-03 15:13:24 -04004322 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004323 GL_INVALID_OPERATION,
4324 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4325 return false;
4326 }
4327 }
4328
4329 return true;
4330}
4331
4332bool ValidateCopyTexSubImage2D(Context *context,
4333 GLenum target,
4334 GLint level,
4335 GLint xoffset,
4336 GLint yoffset,
4337 GLint x,
4338 GLint y,
4339 GLsizei width,
4340 GLsizei height)
4341{
Martin Radev1be913c2016-07-11 17:59:16 +03004342 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004343 {
4344 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4345 yoffset, x, y, width, height, 0);
4346 }
4347
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004348 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4349 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004350}
4351
Geoff Lang496c02d2016-10-20 11:38:11 -07004352bool ValidateGetBufferPointervBase(Context *context,
4353 GLenum target,
4354 GLenum pname,
4355 GLsizei *length,
4356 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004357{
Geoff Lang496c02d2016-10-20 11:38:11 -07004358 if (length)
4359 {
4360 *length = 0;
4361 }
4362
4363 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4364 {
4365 context->handleError(
4366 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004367 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004368 return false;
4369 }
4370
Olli Etuaho4f667482016-03-30 15:56:35 +03004371 if (!ValidBufferTarget(context, target))
4372 {
Jamie Madill437fa652016-05-03 15:13:24 -04004373 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004374 return false;
4375 }
4376
Geoff Lang496c02d2016-10-20 11:38:11 -07004377 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004378 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004379 case GL_BUFFER_MAP_POINTER:
4380 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004381
Geoff Lang496c02d2016-10-20 11:38:11 -07004382 default:
4383 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4384 return false;
4385 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004386
4387 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4388 // target bound to zero generate an INVALID_OPERATION error."
4389 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004390 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004391 {
Jamie Madill437fa652016-05-03 15:13:24 -04004392 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004393 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4394 return false;
4395 }
4396
Geoff Lang496c02d2016-10-20 11:38:11 -07004397 if (length)
4398 {
4399 *length = 1;
4400 }
4401
Olli Etuaho4f667482016-03-30 15:56:35 +03004402 return true;
4403}
4404
4405bool ValidateUnmapBufferBase(Context *context, GLenum target)
4406{
4407 if (!ValidBufferTarget(context, target))
4408 {
Jamie Madill437fa652016-05-03 15:13:24 -04004409 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004410 return false;
4411 }
4412
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004413 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004414
4415 if (buffer == nullptr || !buffer->isMapped())
4416 {
Jamie Madill437fa652016-05-03 15:13:24 -04004417 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004418 return false;
4419 }
4420
4421 return true;
4422}
4423
4424bool ValidateMapBufferRangeBase(Context *context,
4425 GLenum target,
4426 GLintptr offset,
4427 GLsizeiptr length,
4428 GLbitfield access)
4429{
4430 if (!ValidBufferTarget(context, target))
4431 {
Jamie Madill437fa652016-05-03 15:13:24 -04004432 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004433 return false;
4434 }
4435
4436 if (offset < 0 || length < 0)
4437 {
Jamie Madill437fa652016-05-03 15:13:24 -04004438 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004439 return false;
4440 }
4441
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004442 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004443
4444 if (!buffer)
4445 {
Jamie Madill437fa652016-05-03 15:13:24 -04004446 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004447 return false;
4448 }
4449
4450 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004451 CheckedNumeric<size_t> checkedOffset(offset);
4452 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004453
Jamie Madille2e406c2016-06-02 13:04:10 -04004454 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004455 {
Jamie Madill437fa652016-05-03 15:13:24 -04004456 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004457 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4458 return false;
4459 }
4460
4461 // Check for invalid bits in the mask
4462 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4463 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4464 GL_MAP_UNSYNCHRONIZED_BIT;
4465
4466 if (access & ~(allAccessBits))
4467 {
Jamie Madill437fa652016-05-03 15:13:24 -04004468 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004469 return false;
4470 }
4471
4472 if (length == 0)
4473 {
Jamie Madill437fa652016-05-03 15:13:24 -04004474 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004475 return false;
4476 }
4477
4478 if (buffer->isMapped())
4479 {
Jamie Madill437fa652016-05-03 15:13:24 -04004480 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004481 return false;
4482 }
4483
4484 // Check for invalid bit combinations
4485 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4486 {
Jamie Madill437fa652016-05-03 15:13:24 -04004487 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004488 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4489 return false;
4490 }
4491
4492 GLbitfield writeOnlyBits =
4493 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4494
4495 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4496 {
Jamie Madill437fa652016-05-03 15:13:24 -04004497 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004498 "Invalid access bits when mapping buffer for reading: 0x%X.",
4499 access));
4500 return false;
4501 }
4502
4503 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4504 {
Jamie Madill437fa652016-05-03 15:13:24 -04004505 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004506 GL_INVALID_OPERATION,
4507 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4508 return false;
4509 }
4510 return true;
4511}
4512
4513bool ValidateFlushMappedBufferRangeBase(Context *context,
4514 GLenum target,
4515 GLintptr offset,
4516 GLsizeiptr length)
4517{
4518 if (offset < 0 || length < 0)
4519 {
Jamie Madill437fa652016-05-03 15:13:24 -04004520 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004521 return false;
4522 }
4523
4524 if (!ValidBufferTarget(context, target))
4525 {
Jamie Madill437fa652016-05-03 15:13:24 -04004526 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004527 return false;
4528 }
4529
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004530 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004531
4532 if (buffer == nullptr)
4533 {
Jamie Madill437fa652016-05-03 15:13:24 -04004534 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004535 return false;
4536 }
4537
4538 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4539 {
Jamie Madill437fa652016-05-03 15:13:24 -04004540 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004541 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4542 return false;
4543 }
4544
4545 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004546 CheckedNumeric<size_t> checkedOffset(offset);
4547 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004548
Jamie Madille2e406c2016-06-02 13:04:10 -04004549 if (!checkedSize.IsValid() ||
4550 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004551 {
Jamie Madill437fa652016-05-03 15:13:24 -04004552 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004553 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4554 return false;
4555 }
4556
4557 return true;
4558}
4559
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004560bool ValidateGenerateMipmap(Context *context, GLenum target)
4561{
4562 if (!ValidTextureTarget(context, target))
4563 {
4564 context->handleError(Error(GL_INVALID_ENUM));
4565 return false;
4566 }
4567
4568 Texture *texture = context->getTargetTexture(target);
4569
4570 if (texture == nullptr)
4571 {
4572 context->handleError(Error(GL_INVALID_OPERATION));
4573 return false;
4574 }
4575
4576 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4577
4578 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4579 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4580 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4581 {
4582 context->handleError(Error(GL_INVALID_OPERATION));
4583 return false;
4584 }
4585
Jamie Madilla3944d42016-07-22 22:13:26 -04004586 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4587 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4588 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004589
4590 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4591 // unsized formats or that are color renderable and filterable. Since we do not track if
4592 // the texture was created with sized or unsized format (only sized formats are stored),
4593 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4594 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4595 // textures since they're the only texture format that can be created with unsized formats
4596 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4597 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004598 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4599 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004600 {
4601 context->handleError(Error(GL_INVALID_OPERATION));
4602 return false;
4603 }
4604
4605 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004606 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004607 {
4608 context->handleError(Error(GL_INVALID_OPERATION));
4609 return false;
4610 }
4611
4612 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004613 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004614 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4615 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4616 {
Geoff Lang55482a12016-11-21 16:54:01 -05004617 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004618 context->handleError(Error(GL_INVALID_OPERATION));
4619 return false;
4620 }
4621
4622 // Cube completeness check
4623 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4624 {
4625 context->handleError(Error(GL_INVALID_OPERATION));
4626 return false;
4627 }
4628
4629 return true;
4630}
4631
Olli Etuaho41997e72016-03-10 13:38:39 +02004632bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4633{
4634 return ValidateGenOrDelete(context, n);
4635}
4636
4637bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4638{
4639 return ValidateGenOrDelete(context, n);
4640}
4641
4642bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4643{
4644 return ValidateGenOrDelete(context, n);
4645}
4646
4647bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4648{
4649 return ValidateGenOrDelete(context, n);
4650}
4651
4652bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4653{
4654 return ValidateGenOrDelete(context, n);
4655}
4656
4657bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4658{
4659 return ValidateGenOrDelete(context, n);
4660}
4661
4662bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4663{
4664 return ValidateGenOrDelete(context, n);
4665}
4666
4667bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4668{
4669 return ValidateGenOrDelete(context, n);
4670}
4671
4672bool ValidateGenOrDelete(Context *context, GLint n)
4673{
4674 if (n < 0)
4675 {
Jamie Madill437fa652016-05-03 15:13:24 -04004676 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004677 return false;
4678 }
4679 return true;
4680}
4681
Geoff Langf41a7152016-09-19 15:11:17 -04004682bool ValidateEnable(Context *context, GLenum cap)
4683{
4684 if (!ValidCap(context, cap, false))
4685 {
4686 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4687 return false;
4688 }
4689
4690 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4691 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4692 {
4693 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4694 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4695
4696 // We also output an error message to the debugger window if tracing is active, so that
4697 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05004698 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04004699 return false;
4700 }
4701
4702 return true;
4703}
4704
4705bool ValidateDisable(Context *context, GLenum cap)
4706{
4707 if (!ValidCap(context, cap, false))
4708 {
4709 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4710 return false;
4711 }
4712
4713 return true;
4714}
4715
4716bool ValidateIsEnabled(Context *context, GLenum cap)
4717{
4718 if (!ValidCap(context, cap, true))
4719 {
4720 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4721 return false;
4722 }
4723
4724 return true;
4725}
4726
Geoff Langff5b2d52016-09-07 11:32:23 -04004727bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4728{
4729 if (!context->getExtensions().robustClientMemory)
4730 {
4731 context->handleError(
4732 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4733 return false;
4734 }
4735
4736 if (bufSize < 0)
4737 {
4738 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4739 return false;
4740 }
4741
4742 return true;
4743}
4744
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004745bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4746{
4747 if (bufSize < numParams)
4748 {
4749 context->handleError(Error(GL_INVALID_OPERATION,
4750 "%u parameters are required but %i were provided.", numParams,
4751 bufSize));
4752 return false;
4753 }
4754
4755 return true;
4756}
4757
Geoff Langff5b2d52016-09-07 11:32:23 -04004758bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4759 GLenum target,
4760 GLenum attachment,
4761 GLenum pname,
4762 GLsizei *numParams)
4763{
4764 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4765 *numParams = 1;
4766
4767 if (!ValidFramebufferTarget(target))
4768 {
4769 context->handleError(Error(GL_INVALID_ENUM));
4770 return false;
4771 }
4772
4773 int clientVersion = context->getClientMajorVersion();
4774
4775 switch (pname)
4776 {
4777 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4778 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4779 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4780 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4781 break;
4782
4783 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4784 if (clientVersion < 3 && !context->getExtensions().sRGB)
4785 {
4786 context->handleError(Error(GL_INVALID_ENUM));
4787 return false;
4788 }
4789 break;
4790
4791 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4792 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4793 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4794 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4795 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4796 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4797 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4798 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4799 if (clientVersion < 3)
4800 {
4801 context->handleError(Error(GL_INVALID_ENUM));
4802 return false;
4803 }
4804 break;
4805
4806 default:
4807 context->handleError(Error(GL_INVALID_ENUM));
4808 return false;
4809 }
4810
4811 // Determine if the attachment is a valid enum
4812 switch (attachment)
4813 {
4814 case GL_BACK:
4815 case GL_FRONT:
4816 case GL_DEPTH:
4817 case GL_STENCIL:
4818 case GL_DEPTH_STENCIL_ATTACHMENT:
4819 if (clientVersion < 3)
4820 {
4821 context->handleError(Error(GL_INVALID_ENUM));
4822 return false;
4823 }
4824 break;
4825
4826 case GL_DEPTH_ATTACHMENT:
4827 case GL_STENCIL_ATTACHMENT:
4828 break;
4829
4830 default:
4831 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4832 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4833 {
4834 context->handleError(Error(GL_INVALID_ENUM));
4835 return false;
4836 }
4837 break;
4838 }
4839
4840 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4841 ASSERT(framebuffer);
4842
4843 if (framebuffer->id() == 0)
4844 {
4845 if (clientVersion < 3)
4846 {
4847 context->handleError(Error(GL_INVALID_OPERATION));
4848 return false;
4849 }
4850
4851 switch (attachment)
4852 {
4853 case GL_BACK:
4854 case GL_DEPTH:
4855 case GL_STENCIL:
4856 break;
4857
4858 default:
4859 context->handleError(Error(GL_INVALID_OPERATION));
4860 return false;
4861 }
4862 }
4863 else
4864 {
4865 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4866 {
4867 // Valid attachment query
4868 }
4869 else
4870 {
4871 switch (attachment)
4872 {
4873 case GL_DEPTH_ATTACHMENT:
4874 case GL_STENCIL_ATTACHMENT:
4875 break;
4876
4877 case GL_DEPTH_STENCIL_ATTACHMENT:
4878 if (!framebuffer->hasValidDepthStencil())
4879 {
4880 context->handleError(Error(GL_INVALID_OPERATION));
4881 return false;
4882 }
4883 break;
4884
4885 default:
4886 context->handleError(Error(GL_INVALID_OPERATION));
4887 return false;
4888 }
4889 }
4890 }
4891
4892 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4893 if (attachmentObject)
4894 {
4895 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4896 attachmentObject->type() == GL_TEXTURE ||
4897 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4898
4899 switch (pname)
4900 {
4901 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4902 if (attachmentObject->type() != GL_RENDERBUFFER &&
4903 attachmentObject->type() != GL_TEXTURE)
4904 {
4905 context->handleError(Error(GL_INVALID_ENUM));
4906 return false;
4907 }
4908 break;
4909
4910 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4911 if (attachmentObject->type() != GL_TEXTURE)
4912 {
4913 context->handleError(Error(GL_INVALID_ENUM));
4914 return false;
4915 }
4916 break;
4917
4918 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4919 if (attachmentObject->type() != GL_TEXTURE)
4920 {
4921 context->handleError(Error(GL_INVALID_ENUM));
4922 return false;
4923 }
4924 break;
4925
4926 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4927 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4928 {
4929 context->handleError(Error(GL_INVALID_OPERATION));
4930 return false;
4931 }
4932 break;
4933
4934 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4935 if (attachmentObject->type() != GL_TEXTURE)
4936 {
4937 context->handleError(Error(GL_INVALID_ENUM));
4938 return false;
4939 }
4940 break;
4941
4942 default:
4943 break;
4944 }
4945 }
4946 else
4947 {
4948 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4949 // is NONE, then querying any other pname will generate INVALID_ENUM.
4950
4951 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4952 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4953 // INVALID_OPERATION for all other pnames
4954
4955 switch (pname)
4956 {
4957 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4958 break;
4959
4960 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4961 if (clientVersion < 3)
4962 {
4963 context->handleError(Error(GL_INVALID_ENUM));
4964 return false;
4965 }
4966 break;
4967
4968 default:
4969 if (clientVersion < 3)
4970 {
4971 context->handleError(Error(GL_INVALID_ENUM));
4972 return false;
4973 }
4974 else
4975 {
4976 context->handleError(Error(GL_INVALID_OPERATION));
4977 return false;
4978 }
4979 }
4980 }
4981
4982 return true;
4983}
4984
4985bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4986 GLenum target,
4987 GLenum attachment,
4988 GLenum pname,
4989 GLsizei bufSize,
4990 GLsizei *numParams)
4991{
4992 if (!ValidateRobustEntryPoint(context, bufSize))
4993 {
4994 return false;
4995 }
4996
4997 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4998 {
4999 return false;
5000 }
5001
5002 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5003 {
5004 return false;
5005 }
5006
5007 return true;
5008}
5009
5010bool ValidateGetBufferParameteriv(ValidationContext *context,
5011 GLenum target,
5012 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005013 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005014{
Geoff Langebebe1c2016-10-14 12:01:31 -04005015 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005016}
5017
5018bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5019 GLenum target,
5020 GLenum pname,
5021 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005022 GLsizei *length,
5023 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005024{
5025 if (!ValidateRobustEntryPoint(context, bufSize))
5026 {
5027 return false;
5028 }
5029
Geoff Langebebe1c2016-10-14 12:01:31 -04005030 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005031 {
5032 return false;
5033 }
5034
Geoff Langebebe1c2016-10-14 12:01:31 -04005035 if (!ValidateRobustBufferSize(context, bufSize, *length))
5036 {
5037 return false;
5038 }
5039
5040 return true;
5041}
5042
5043bool ValidateGetBufferParameteri64v(ValidationContext *context,
5044 GLenum target,
5045 GLenum pname,
5046 GLint64 *params)
5047{
5048 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5049}
5050
5051bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5052 GLenum target,
5053 GLenum pname,
5054 GLsizei bufSize,
5055 GLsizei *length,
5056 GLint64 *params)
5057{
5058 if (!ValidateRobustEntryPoint(context, bufSize))
5059 {
5060 return false;
5061 }
5062
5063 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5064 {
5065 return false;
5066 }
5067
5068 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005069 {
5070 return false;
5071 }
5072
5073 return true;
5074}
5075
5076bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5077{
5078 // Currently, all GetProgramiv queries return 1 parameter
5079 *numParams = 1;
5080
5081 Program *programObject = GetValidProgram(context, program);
5082 if (!programObject)
5083 {
5084 return false;
5085 }
5086
5087 switch (pname)
5088 {
5089 case GL_DELETE_STATUS:
5090 case GL_LINK_STATUS:
5091 case GL_VALIDATE_STATUS:
5092 case GL_INFO_LOG_LENGTH:
5093 case GL_ATTACHED_SHADERS:
5094 case GL_ACTIVE_ATTRIBUTES:
5095 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5096 case GL_ACTIVE_UNIFORMS:
5097 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5098 break;
5099
5100 case GL_PROGRAM_BINARY_LENGTH:
5101 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5102 {
5103 context->handleError(Error(GL_INVALID_ENUM,
5104 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5105 "GL_OES_get_program_binary or ES 3.0."));
5106 return false;
5107 }
5108 break;
5109
5110 case GL_ACTIVE_UNIFORM_BLOCKS:
5111 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5112 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5113 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5114 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5115 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5116 if (context->getClientMajorVersion() < 3)
5117 {
5118 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5119 return false;
5120 }
5121 break;
5122
5123 default:
5124 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5125 return false;
5126 }
5127
5128 return true;
5129}
5130
5131bool ValidateGetProgramivRobustANGLE(Context *context,
5132 GLuint program,
5133 GLenum pname,
5134 GLsizei bufSize,
5135 GLsizei *numParams)
5136{
5137 if (!ValidateRobustEntryPoint(context, bufSize))
5138 {
5139 return false;
5140 }
5141
5142 if (!ValidateGetProgramiv(context, program, pname, numParams))
5143 {
5144 return false;
5145 }
5146
5147 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5148 {
5149 return false;
5150 }
5151
5152 return true;
5153}
5154
Geoff Lang740d9022016-10-07 11:20:52 -04005155bool ValidateGetRenderbufferParameteriv(Context *context,
5156 GLenum target,
5157 GLenum pname,
5158 GLint *params)
5159{
5160 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5161}
5162
5163bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5164 GLenum target,
5165 GLenum pname,
5166 GLsizei bufSize,
5167 GLsizei *length,
5168 GLint *params)
5169{
5170 if (!ValidateRobustEntryPoint(context, bufSize))
5171 {
5172 return false;
5173 }
5174
5175 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5176 {
5177 return false;
5178 }
5179
5180 if (!ValidateRobustBufferSize(context, bufSize, *length))
5181 {
5182 return false;
5183 }
5184
5185 return true;
5186}
5187
Geoff Langd7d0ed32016-10-07 11:33:51 -04005188bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5189{
5190 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5191}
5192
5193bool ValidateGetShaderivRobustANGLE(Context *context,
5194 GLuint shader,
5195 GLenum pname,
5196 GLsizei bufSize,
5197 GLsizei *length,
5198 GLint *params)
5199{
5200 if (!ValidateRobustEntryPoint(context, bufSize))
5201 {
5202 return false;
5203 }
5204
5205 if (!ValidateGetShaderivBase(context, shader, pname, length))
5206 {
5207 return false;
5208 }
5209
5210 if (!ValidateRobustBufferSize(context, bufSize, *length))
5211 {
5212 return false;
5213 }
5214
5215 return true;
5216}
5217
Geoff Langc1984ed2016-10-07 12:41:00 -04005218bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5219{
5220 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5221}
5222
5223bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5224 GLenum target,
5225 GLenum pname,
5226 GLsizei bufSize,
5227 GLsizei *length,
5228 GLfloat *params)
5229{
5230 if (!ValidateRobustEntryPoint(context, bufSize))
5231 {
5232 return false;
5233 }
5234
5235 if (!ValidateGetTexParameterBase(context, target, pname, length))
5236 {
5237 return false;
5238 }
5239
5240 if (!ValidateRobustBufferSize(context, bufSize, *length))
5241 {
5242 return false;
5243 }
5244
5245 return true;
5246}
5247
5248bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5249{
5250 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5251}
5252
5253bool ValidateGetTexParameterivRobustANGLE(Context *context,
5254 GLenum target,
5255 GLenum pname,
5256 GLsizei bufSize,
5257 GLsizei *length,
5258 GLint *params)
5259{
5260 if (!ValidateRobustEntryPoint(context, bufSize))
5261 {
5262 return false;
5263 }
5264
5265 if (!ValidateGetTexParameterBase(context, target, pname, length))
5266 {
5267 return false;
5268 }
5269
5270 if (!ValidateRobustBufferSize(context, bufSize, *length))
5271 {
5272 return false;
5273 }
5274
5275 return true;
5276}
5277
5278bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5279{
5280 return ValidateTexParameterBase(context, target, pname, -1, &param);
5281}
5282
5283bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5284{
5285 return ValidateTexParameterBase(context, target, pname, -1, params);
5286}
5287
5288bool ValidateTexParameterfvRobustANGLE(Context *context,
5289 GLenum target,
5290 GLenum pname,
5291 GLsizei bufSize,
5292 const GLfloat *params)
5293{
5294 if (!ValidateRobustEntryPoint(context, bufSize))
5295 {
5296 return false;
5297 }
5298
5299 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5300}
5301
5302bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5303{
5304 return ValidateTexParameterBase(context, target, pname, -1, &param);
5305}
5306
5307bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5308{
5309 return ValidateTexParameterBase(context, target, pname, -1, params);
5310}
5311
5312bool ValidateTexParameterivRobustANGLE(Context *context,
5313 GLenum target,
5314 GLenum pname,
5315 GLsizei bufSize,
5316 const GLint *params)
5317{
5318 if (!ValidateRobustEntryPoint(context, bufSize))
5319 {
5320 return false;
5321 }
5322
5323 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5324}
5325
5326bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5327{
5328 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5329}
5330
5331bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5332 GLuint sampler,
5333 GLenum pname,
5334 GLuint bufSize,
5335 GLsizei *length,
5336 GLfloat *params)
5337{
5338 if (!ValidateRobustEntryPoint(context, bufSize))
5339 {
5340 return false;
5341 }
5342
5343 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5344 {
5345 return false;
5346 }
5347
5348 if (!ValidateRobustBufferSize(context, bufSize, *length))
5349 {
5350 return false;
5351 }
5352
5353 return true;
5354}
5355
5356bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5357{
5358 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5359}
5360
5361bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5362 GLuint sampler,
5363 GLenum pname,
5364 GLuint bufSize,
5365 GLsizei *length,
5366 GLint *params)
5367{
5368 if (!ValidateRobustEntryPoint(context, bufSize))
5369 {
5370 return false;
5371 }
5372
5373 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5374 {
5375 return false;
5376 }
5377
5378 if (!ValidateRobustBufferSize(context, bufSize, *length))
5379 {
5380 return false;
5381 }
5382
5383 return true;
5384}
5385
5386bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5387{
5388 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5389}
5390
5391bool ValidateSamplerParameterfv(Context *context,
5392 GLuint sampler,
5393 GLenum pname,
5394 const GLfloat *params)
5395{
5396 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5397}
5398
5399bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5400 GLuint sampler,
5401 GLenum pname,
5402 GLsizei bufSize,
5403 const GLfloat *params)
5404{
5405 if (!ValidateRobustEntryPoint(context, bufSize))
5406 {
5407 return false;
5408 }
5409
5410 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5411}
5412
5413bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5414{
5415 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5416}
5417
5418bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5419{
5420 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5421}
5422
5423bool ValidateSamplerParameterivRobustANGLE(Context *context,
5424 GLuint sampler,
5425 GLenum pname,
5426 GLsizei bufSize,
5427 const GLint *params)
5428{
5429 if (!ValidateRobustEntryPoint(context, bufSize))
5430 {
5431 return false;
5432 }
5433
5434 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5435}
5436
Geoff Lang0b031062016-10-13 14:30:04 -04005437bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5438{
5439 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5440}
5441
5442bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5443 GLuint index,
5444 GLenum pname,
5445 GLsizei bufSize,
5446 GLsizei *length,
5447 GLfloat *params)
5448{
5449 if (!ValidateRobustEntryPoint(context, bufSize))
5450 {
5451 return false;
5452 }
5453
5454 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5455 {
5456 return false;
5457 }
5458
5459 if (!ValidateRobustBufferSize(context, bufSize, *length))
5460 {
5461 return false;
5462 }
5463
5464 return true;
5465}
5466
5467bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5468{
5469 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5470}
5471
5472bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5473 GLuint index,
5474 GLenum pname,
5475 GLsizei bufSize,
5476 GLsizei *length,
5477 GLint *params)
5478{
5479 if (!ValidateRobustEntryPoint(context, bufSize))
5480 {
5481 return false;
5482 }
5483
5484 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5485 {
5486 return false;
5487 }
5488
5489 if (!ValidateRobustBufferSize(context, bufSize, *length))
5490 {
5491 return false;
5492 }
5493
5494 return true;
5495}
5496
5497bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5498{
5499 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5500}
5501
5502bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5503 GLuint index,
5504 GLenum pname,
5505 GLsizei bufSize,
5506 GLsizei *length,
5507 void **pointer)
5508{
5509 if (!ValidateRobustEntryPoint(context, bufSize))
5510 {
5511 return false;
5512 }
5513
5514 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5515 {
5516 return false;
5517 }
5518
5519 if (!ValidateRobustBufferSize(context, bufSize, *length))
5520 {
5521 return false;
5522 }
5523
5524 return true;
5525}
5526
5527bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5528{
5529 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5530}
5531
5532bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5533 GLuint index,
5534 GLenum pname,
5535 GLsizei bufSize,
5536 GLsizei *length,
5537 GLint *params)
5538{
5539 if (!ValidateRobustEntryPoint(context, bufSize))
5540 {
5541 return false;
5542 }
5543
5544 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5545 {
5546 return false;
5547 }
5548
5549 if (!ValidateRobustBufferSize(context, bufSize, *length))
5550 {
5551 return false;
5552 }
5553
5554 return true;
5555}
5556
5557bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5558{
5559 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5560}
5561
5562bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5563 GLuint index,
5564 GLenum pname,
5565 GLsizei bufSize,
5566 GLsizei *length,
5567 GLuint *params)
5568{
5569 if (!ValidateRobustEntryPoint(context, bufSize))
5570 {
5571 return false;
5572 }
5573
5574 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5575 {
5576 return false;
5577 }
5578
5579 if (!ValidateRobustBufferSize(context, bufSize, *length))
5580 {
5581 return false;
5582 }
5583
5584 return true;
5585}
5586
Geoff Lang6899b872016-10-14 11:30:13 -04005587bool ValidateGetActiveUniformBlockiv(Context *context,
5588 GLuint program,
5589 GLuint uniformBlockIndex,
5590 GLenum pname,
5591 GLint *params)
5592{
5593 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5594}
5595
5596bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5597 GLuint program,
5598 GLuint uniformBlockIndex,
5599 GLenum pname,
5600 GLsizei bufSize,
5601 GLsizei *length,
5602 GLint *params)
5603{
5604 if (!ValidateRobustEntryPoint(context, bufSize))
5605 {
5606 return false;
5607 }
5608
5609 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5610 {
5611 return false;
5612 }
5613
5614 if (!ValidateRobustBufferSize(context, bufSize, *length))
5615 {
5616 return false;
5617 }
5618
5619 return true;
5620}
5621
Geoff Lang0a9661f2016-10-20 10:59:20 -07005622bool ValidateGetInternalFormativ(Context *context,
5623 GLenum target,
5624 GLenum internalformat,
5625 GLenum pname,
5626 GLsizei bufSize,
5627 GLint *params)
5628{
5629 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5630 nullptr);
5631}
5632
5633bool ValidateGetInternalFormativRobustANGLE(Context *context,
5634 GLenum target,
5635 GLenum internalformat,
5636 GLenum pname,
5637 GLsizei bufSize,
5638 GLsizei *length,
5639 GLint *params)
5640{
5641 if (!ValidateRobustEntryPoint(context, bufSize))
5642 {
5643 return false;
5644 }
5645
5646 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5647 {
5648 return false;
5649 }
5650
5651 if (!ValidateRobustBufferSize(context, bufSize, *length))
5652 {
5653 return false;
5654 }
5655
5656 return true;
5657}
5658
Jamie Madillc29968b2016-01-20 11:17:23 -05005659} // namespace gl