blob: 5804c563880ff2f7a0e73104ec1f370f96363fbb [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
Frank Henigman999b0fd2017-02-02 21:45:55 -05001420bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -05001421 GLenum uniformType,
1422 GLsizei count,
1423 const GLint *value)
1424{
1425 // Value type is GL_INT, because we only get here from glUniform1i{v}.
1426 // It is compatible with INT or BOOL.
1427 // Do these cheap tests first, for a little extra speed.
1428 if (GL_INT == uniformType || GL_BOOL == uniformType)
1429 {
1430 return true;
1431 }
1432
1433 if (IsSamplerType(uniformType))
1434 {
Frank Henigman999b0fd2017-02-02 21:45:55 -05001435 // Check that the values are in range.
1436 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
1437 for (GLsizei i = 0; i < count; ++i)
1438 {
1439 if (value[i] < 0 || value[i] >= max)
1440 {
1441 context->handleError(Error(GL_INVALID_VALUE, "sampler uniform value out of range"));
1442 return false;
1443 }
1444 }
Frank Henigmana98a6472017-02-02 21:38:32 -05001445 return true;
1446 }
1447
1448 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1449 return false;
1450}
1451
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001452bool ValidateUniformValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1453{
1454 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -05001455 // Do the cheaper test first, for a little extra speed.
1456 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001457 {
1458 return true;
1459 }
1460
1461 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1462 return false;
1463}
1464
1465bool ValidateUniformMatrixValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1466{
1467 // Check that the value type is compatible with uniform type.
1468 if (valueType == uniformType)
1469 {
1470 return true;
1471 }
1472
1473 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1474 return false;
1475}
1476
Geoff Langf41a7152016-09-19 15:11:17 -04001477} // anonymous namespace
1478
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001479bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001480{
Jamie Madilld7460c72014-01-21 16:38:14 -05001481 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001482 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001483 case GL_TEXTURE_2D:
1484 case GL_TEXTURE_CUBE_MAP:
1485 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001486
He Yunchaoced53ae2016-11-29 15:00:51 +08001487 case GL_TEXTURE_3D:
1488 case GL_TEXTURE_2D_ARRAY:
1489 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001490
He Yunchaoced53ae2016-11-29 15:00:51 +08001491 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001492 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001493
He Yunchaoced53ae2016-11-29 15:00:51 +08001494 default:
1495 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001496 }
Jamie Madill35d15012013-10-07 10:46:37 -04001497}
1498
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001499bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1500{
1501 switch (target)
1502 {
1503 case GL_TEXTURE_2D:
1504 case GL_TEXTURE_CUBE_MAP:
1505 return true;
1506
1507 default:
1508 return false;
1509 }
1510}
1511
1512bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1513{
1514 switch (target)
1515 {
1516 case GL_TEXTURE_3D:
1517 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001518 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001519
1520 default:
1521 return false;
1522 }
1523}
1524
Ian Ewellbda75592016-04-18 17:25:54 -04001525// Most texture GL calls are not compatible with external textures, so we have a separate validation
1526// function for use in the GL calls that do
1527bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1528{
1529 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1530 (context->getExtensions().eglImageExternal ||
1531 context->getExtensions().eglStreamConsumerExternal);
1532}
1533
Shannon Woods4dfed832014-03-17 20:03:39 -04001534// This function differs from ValidTextureTarget in that the target must be
1535// usable as the destination of a 2D operation-- so a cube face is valid, but
1536// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001537// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001538bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001539{
1540 switch (target)
1541 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001542 case GL_TEXTURE_2D:
1543 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1544 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1545 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1546 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1547 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1548 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1549 return true;
1550 default:
1551 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001552 }
1553}
1554
1555bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1556{
1557 switch (target)
1558 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001559 case GL_TEXTURE_3D:
1560 case GL_TEXTURE_2D_ARRAY:
1561 return true;
1562 default:
1563 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001564 }
1565}
1566
He Yunchao11b038b2016-11-22 21:24:04 +08001567bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1568{
1569 switch (target)
1570 {
1571 case GL_TEXTURE_2D:
1572 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1573 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1574 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1575 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1576 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1577 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1578 case GL_TEXTURE_3D:
1579 case GL_TEXTURE_2D_ARRAY:
1580 case GL_TEXTURE_2D_MULTISAMPLE:
1581 return true;
1582 default:
1583 return false;
1584 }
1585}
1586
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001587bool ValidFramebufferTarget(GLenum target)
1588{
He Yunchaoced53ae2016-11-29 15:00:51 +08001589 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1590 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001591 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001592
1593 switch (target)
1594 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001595 case GL_FRAMEBUFFER:
1596 return true;
1597 case GL_READ_FRAMEBUFFER:
1598 return true;
1599 case GL_DRAW_FRAMEBUFFER:
1600 return true;
1601 default:
1602 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001603 }
1604}
1605
Jamie Madill29639852016-09-02 15:00:09 -04001606bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001607{
1608 switch (target)
1609 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001610 case GL_ARRAY_BUFFER:
1611 case GL_ELEMENT_ARRAY_BUFFER:
1612 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001613
He Yunchaoced53ae2016-11-29 15:00:51 +08001614 case GL_PIXEL_PACK_BUFFER:
1615 case GL_PIXEL_UNPACK_BUFFER:
1616 return (context->getExtensions().pixelBufferObject ||
1617 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001618
He Yunchaoced53ae2016-11-29 15:00:51 +08001619 case GL_COPY_READ_BUFFER:
1620 case GL_COPY_WRITE_BUFFER:
1621 case GL_TRANSFORM_FEEDBACK_BUFFER:
1622 case GL_UNIFORM_BUFFER:
1623 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001624
He Yunchaoced53ae2016-11-29 15:00:51 +08001625 case GL_ATOMIC_COUNTER_BUFFER:
1626 case GL_SHADER_STORAGE_BUFFER:
1627 case GL_DRAW_INDIRECT_BUFFER:
1628 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001629 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001630
He Yunchaoced53ae2016-11-29 15:00:51 +08001631 default:
1632 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001633 }
1634}
1635
Jamie Madillc29968b2016-01-20 11:17:23 -05001636bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001637{
Jamie Madillc29968b2016-01-20 11:17:23 -05001638 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001639 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001640 switch (target)
1641 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001642 case GL_TEXTURE_2D:
1643 maxDimension = caps.max2DTextureSize;
1644 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001645 case GL_TEXTURE_CUBE_MAP:
1646 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1647 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1648 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1649 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1650 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1651 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1652 maxDimension = caps.maxCubeMapTextureSize;
1653 break;
1654 case GL_TEXTURE_3D:
1655 maxDimension = caps.max3DTextureSize;
1656 break;
1657 case GL_TEXTURE_2D_ARRAY:
1658 maxDimension = caps.max2DTextureSize;
1659 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001660 case GL_TEXTURE_2D_MULTISAMPLE:
1661 maxDimension = caps.max2DTextureSize;
1662 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001663 default:
1664 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001665 }
1666
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001667 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001668}
1669
Geoff Langcc507aa2016-12-12 10:09:52 -05001670bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001671 GLenum target,
1672 GLint level,
1673 GLsizei width,
1674 GLsizei height,
1675 GLsizei depth,
1676 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001677{
1678 if (level < 0 || width < 0 || height < 0 || depth < 0)
1679 {
1680 return false;
1681 }
1682
Austin Kinross08528e12015-10-07 16:24:40 -07001683 // TexSubImage parameters can be NPOT without textureNPOT extension,
1684 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001685 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001686 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001687 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001688 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001689 {
1690 return false;
1691 }
1692
1693 if (!ValidMipLevel(context, target, level))
1694 {
1695 return false;
1696 }
1697
1698 return true;
1699}
1700
Geoff Lang0d8b7242015-09-09 14:56:53 -04001701bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1702{
1703 // List of compressed format that require that the texture size is smaller than or a multiple of
1704 // the compressed block size.
1705 switch (internalFormat)
1706 {
1707 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1708 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1709 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1710 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001711 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001712 return true;
1713
1714 default:
1715 return false;
1716 }
1717}
1718
Jamie Madillc29968b2016-01-20 11:17:23 -05001719bool ValidCompressedImageSize(const ValidationContext *context,
1720 GLenum internalFormat,
Geoff Lang44ff5a72017-02-03 15:15:43 -05001721 GLint xoffset,
1722 GLint yoffset,
Jamie Madillc29968b2016-01-20 11:17:23 -05001723 GLsizei width,
1724 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001725{
Geoff Lang5d601382014-07-22 15:14:06 -04001726 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1727 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001728 {
1729 return false;
1730 }
1731
Geoff Lang44ff5a72017-02-03 15:15:43 -05001732 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001733 {
1734 return false;
1735 }
1736
Geoff Lang0d8b7242015-09-09 14:56:53 -04001737 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1738 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001739 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
1740 yoffset % formatInfo.compressedBlockHeight != 0 ||
1741 (static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
Geoff Lang0d8b7242015-09-09 14:56:53 -04001742 width % formatInfo.compressedBlockWidth != 0) ||
1743 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1744 height % formatInfo.compressedBlockHeight != 0))
1745 {
1746 return false;
1747 }
1748 }
1749
Geoff Langd4f180b2013-09-24 13:57:44 -04001750 return true;
1751}
1752
Geoff Langff5b2d52016-09-07 11:32:23 -04001753bool ValidImageDataSize(ValidationContext *context,
1754 GLenum textureTarget,
1755 GLsizei width,
1756 GLsizei height,
1757 GLsizei depth,
1758 GLenum internalFormat,
1759 GLenum type,
1760 const GLvoid *pixels,
1761 GLsizei imageSize)
1762{
1763 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1764 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1765 {
1766 // Checks are not required
1767 return true;
1768 }
1769
1770 // ...the data would be unpacked from the buffer object such that the memory reads required
1771 // would exceed the data store size.
1772 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1773 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1774 const gl::Extents size(width, height, depth);
1775 const auto &unpack = context->getGLState().getUnpackState();
1776
1777 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1778 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1779 if (endByteOrErr.isError())
1780 {
1781 context->handleError(endByteOrErr.getError());
1782 return false;
1783 }
1784
1785 GLuint endByte = endByteOrErr.getResult();
1786
1787 if (pixelUnpackBuffer)
1788 {
1789 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1790 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1791 checkedEndByte += checkedOffset;
1792
1793 if (!checkedEndByte.IsValid() ||
1794 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1795 {
1796 // Overflow past the end of the buffer
1797 context->handleError(Error(GL_INVALID_OPERATION));
1798 return false;
1799 }
1800 }
1801 else
1802 {
1803 ASSERT(imageSize >= 0);
1804 if (pixels == nullptr && imageSize != 0)
1805 {
1806 context->handleError(
1807 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001808 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001809 }
1810
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001811 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001812 {
1813 context->handleError(
1814 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1815 return false;
1816 }
1817 }
1818
1819 return true;
1820}
1821
Geoff Lang37dde692014-01-31 16:34:54 -05001822bool ValidQueryType(const Context *context, GLenum queryType)
1823{
He Yunchaoced53ae2016-11-29 15:00:51 +08001824 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1825 "GL extension enums not equal.");
1826 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1827 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001828
1829 switch (queryType)
1830 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001831 case GL_ANY_SAMPLES_PASSED:
1832 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1833 return true;
1834 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1835 return (context->getClientMajorVersion() >= 3);
1836 case GL_TIME_ELAPSED_EXT:
1837 return context->getExtensions().disjointTimerQuery;
1838 case GL_COMMANDS_COMPLETED_CHROMIUM:
1839 return context->getExtensions().syncQuery;
1840 default:
1841 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001842 }
1843}
1844
Jamie Madillef300b12016-10-07 15:12:09 -04001845Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001846{
He Yunchaoced53ae2016-11-29 15:00:51 +08001847 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1848 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1849 // or program object and INVALID_OPERATION if the provided name identifies an object
1850 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001851
Dian Xiang769769a2015-09-09 15:20:08 -07001852 Program *validProgram = context->getProgram(id);
1853
1854 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001855 {
Dian Xiang769769a2015-09-09 15:20:08 -07001856 if (context->getShader(id))
1857 {
Jamie Madill437fa652016-05-03 15:13:24 -04001858 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001859 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1860 }
1861 else
1862 {
Jamie Madill437fa652016-05-03 15:13:24 -04001863 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001864 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001865 }
Dian Xiang769769a2015-09-09 15:20:08 -07001866
1867 return validProgram;
1868}
1869
Jamie Madillef300b12016-10-07 15:12:09 -04001870Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001871{
1872 // See ValidProgram for spec details.
1873
1874 Shader *validShader = context->getShader(id);
1875
1876 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001877 {
Dian Xiang769769a2015-09-09 15:20:08 -07001878 if (context->getProgram(id))
1879 {
Jamie Madill437fa652016-05-03 15:13:24 -04001880 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001881 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1882 }
1883 else
1884 {
Jamie Madill437fa652016-05-03 15:13:24 -04001885 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001886 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001887 }
Dian Xiang769769a2015-09-09 15:20:08 -07001888
1889 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001890}
1891
Geoff Langb1196682014-07-23 13:47:29 -04001892bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001893{
1894 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1895 {
1896 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1897
Geoff Langaae65a42014-05-26 12:43:44 -04001898 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001899 {
Jamie Madill437fa652016-05-03 15:13:24 -04001900 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001901 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001902 }
1903 }
1904 else
1905 {
1906 switch (attachment)
1907 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001908 case GL_DEPTH_ATTACHMENT:
1909 case GL_STENCIL_ATTACHMENT:
1910 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001911
He Yunchaoced53ae2016-11-29 15:00:51 +08001912 case GL_DEPTH_STENCIL_ATTACHMENT:
1913 if (!context->getExtensions().webglCompatibility &&
1914 context->getClientMajorVersion() < 3)
1915 {
1916 context->handleError(Error(GL_INVALID_ENUM));
1917 return false;
1918 }
1919 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001920
He Yunchaoced53ae2016-11-29 15:00:51 +08001921 default:
1922 context->handleError(Error(GL_INVALID_ENUM));
1923 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001924 }
1925 }
1926
1927 return true;
1928}
1929
Jamie Madille8fb6402017-02-14 17:56:40 -05001930bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001931 GLenum target,
1932 GLsizei samples,
1933 GLenum internalformat,
1934 GLsizei width,
1935 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001936{
1937 switch (target)
1938 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001939 case GL_RENDERBUFFER:
1940 break;
1941 default:
1942 context->handleError(Error(GL_INVALID_ENUM));
1943 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001944 }
1945
1946 if (width < 0 || height < 0 || samples < 0)
1947 {
Jamie Madill437fa652016-05-03 15:13:24 -04001948 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001949 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001950 }
1951
Geoff Langd87878e2014-09-19 15:42:59 -04001952 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1953 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001954 {
Jamie Madill437fa652016-05-03 15:13:24 -04001955 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001956 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001957 }
1958
1959 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1960 // 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 -08001961 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001962 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001963 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001964 {
Jamie Madill437fa652016-05-03 15:13:24 -04001965 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001966 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001967 }
1968
Geoff Langaae65a42014-05-26 12:43:44 -04001969 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001970 {
Jamie Madill437fa652016-05-03 15:13:24 -04001971 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001972 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001973 }
1974
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001975 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001976 if (handle == 0)
1977 {
Jamie Madill437fa652016-05-03 15:13:24 -04001978 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001979 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001980 }
1981
1982 return true;
1983}
1984
He Yunchaoced53ae2016-11-29 15:00:51 +08001985bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1986 GLenum target,
1987 GLenum attachment,
1988 GLenum renderbuffertarget,
1989 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001990{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001991 if (!ValidFramebufferTarget(target))
1992 {
Jamie Madill437fa652016-05-03 15:13:24 -04001993 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001994 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001995 }
1996
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001997 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001998
Jamie Madill84115c92015-04-23 15:00:07 -04001999 ASSERT(framebuffer);
2000 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002001 {
Jamie Madill437fa652016-05-03 15:13:24 -04002002 context->handleError(
2003 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002004 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002005 }
2006
Jamie Madillb4472272014-07-03 10:38:55 -04002007 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002008 {
Jamie Madillb4472272014-07-03 10:38:55 -04002009 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002010 }
2011
Jamie Madillab9d82c2014-01-21 16:38:14 -05002012 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2013 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2014 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2015 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2016 if (renderbuffer != 0)
2017 {
2018 if (!context->getRenderbuffer(renderbuffer))
2019 {
Jamie Madill437fa652016-05-03 15:13:24 -04002020 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002021 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05002022 }
2023 }
2024
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002025 return true;
2026}
2027
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002028bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002029 GLint srcX0,
2030 GLint srcY0,
2031 GLint srcX1,
2032 GLint srcY1,
2033 GLint dstX0,
2034 GLint dstY0,
2035 GLint dstX1,
2036 GLint dstY1,
2037 GLbitfield mask,
2038 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002039{
2040 switch (filter)
2041 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002042 case GL_NEAREST:
2043 break;
2044 case GL_LINEAR:
2045 break;
2046 default:
2047 context->handleError(Error(GL_INVALID_ENUM));
2048 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002049 }
2050
2051 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
2052 {
Jamie Madill437fa652016-05-03 15:13:24 -04002053 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002054 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002055 }
2056
2057 if (mask == 0)
2058 {
2059 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
2060 // buffers are copied.
2061 return false;
2062 }
2063
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002064 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
2065 // color buffer, leaving only nearest being unfiltered from above
2066 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
2067 {
Jamie Madill437fa652016-05-03 15:13:24 -04002068 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002069 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002070 }
2071
Jamie Madill51f40ec2016-06-15 14:06:00 -04002072 const auto &glState = context->getGLState();
2073 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2074 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05002075
2076 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002077 {
Jamie Madill437fa652016-05-03 15:13:24 -04002078 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002079 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002080 }
2081
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002082 if (readFramebuffer->id() == drawFramebuffer->id())
2083 {
2084 context->handleError(Error(GL_INVALID_OPERATION));
2085 return false;
2086 }
2087
Jamie Madill51f40ec2016-06-15 14:06:00 -04002088 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002089 {
Jamie Madill437fa652016-05-03 15:13:24 -04002090 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002091 return false;
2092 }
2093
Jamie Madill51f40ec2016-06-15 14:06:00 -04002094 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002095 {
Jamie Madill437fa652016-05-03 15:13:24 -04002096 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002097 return false;
2098 }
2099
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002100 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002101 {
Jamie Madill437fa652016-05-03 15:13:24 -04002102 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002103 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002104 }
2105
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002106 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2107
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002108 if (mask & GL_COLOR_BUFFER_BIT)
2109 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002110 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002111 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002112
He Yunchao66a41a22016-12-15 16:45:05 +08002113 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002114 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002115 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002116
Geoff Langa15472a2015-08-11 11:48:03 -04002117 for (size_t drawbufferIdx = 0;
2118 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002119 {
Geoff Langa15472a2015-08-11 11:48:03 -04002120 const FramebufferAttachment *attachment =
2121 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2122 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002123 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002124 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002125
Geoff Langb2f3d052013-08-13 12:49:27 -04002126 // The GL ES 3.0.2 spec (pg 193) states that:
2127 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002128 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2129 // as well
2130 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2131 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002132 // Changes with EXT_color_buffer_float:
2133 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002134 GLenum readComponentType = readFormat.info->componentType;
2135 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002136 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002137 readComponentType == GL_SIGNED_NORMALIZED);
2138 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2139 drawComponentType == GL_SIGNED_NORMALIZED);
2140
2141 if (extensions.colorBufferFloat)
2142 {
2143 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2144 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2145
2146 if (readFixedOrFloat != drawFixedOrFloat)
2147 {
Jamie Madill437fa652016-05-03 15:13:24 -04002148 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002149 "If the read buffer contains fixed-point or "
2150 "floating-point values, the draw buffer "
2151 "must as well."));
2152 return false;
2153 }
2154 }
2155 else if (readFixedPoint != drawFixedPoint)
2156 {
Jamie Madill437fa652016-05-03 15:13:24 -04002157 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002158 "If the read buffer contains fixed-point "
2159 "values, the draw buffer must as well."));
2160 return false;
2161 }
2162
2163 if (readComponentType == GL_UNSIGNED_INT &&
2164 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002165 {
Jamie Madill437fa652016-05-03 15:13:24 -04002166 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002167 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002168 }
2169
Jamie Madill6163c752015-12-07 16:32:59 -05002170 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002171 {
Jamie Madill437fa652016-05-03 15:13:24 -04002172 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002173 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002174 }
2175
Jamie Madilla3944d42016-07-22 22:13:26 -04002176 if (readColorBuffer->getSamples() > 0 &&
2177 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002178 {
Jamie Madill437fa652016-05-03 15:13:24 -04002179 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002180 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002181 }
2182 }
2183 }
2184
Jamie Madilla3944d42016-07-22 22:13:26 -04002185 if ((readFormat.info->componentType == GL_INT ||
2186 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2187 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002188 {
Jamie Madill437fa652016-05-03 15:13:24 -04002189 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002190 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002191 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002192 }
He Yunchao66a41a22016-12-15 16:45:05 +08002193 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2194 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2195 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2196 // situation is an application error that would lead to a crash in ANGLE.
2197 else if (drawFramebuffer->hasEnabledDrawBuffer())
2198 {
2199 context->handleError(Error(
2200 GL_INVALID_OPERATION,
2201 "Attempt to read from a missing color attachment of a complete framebuffer."));
2202 return false;
2203 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002204 }
2205
He Yunchaoced53ae2016-11-29 15:00:51 +08002206 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002207 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2208 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002209 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002210 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002211 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002212 const gl::FramebufferAttachment *readBuffer =
2213 readFramebuffer->getAttachment(attachments[i]);
2214 const gl::FramebufferAttachment *drawBuffer =
2215 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002216
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002217 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002218 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002219 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002220 {
Jamie Madill437fa652016-05-03 15:13:24 -04002221 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002222 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002223 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002224
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002225 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002226 {
Jamie Madill437fa652016-05-03 15:13:24 -04002227 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002228 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002229 }
2230 }
He Yunchao66a41a22016-12-15 16:45:05 +08002231 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2232 else if (drawBuffer)
2233 {
2234 context->handleError(Error(GL_INVALID_OPERATION,
2235 "Attempt to read from a missing depth/stencil "
2236 "attachment of a complete framebuffer."));
2237 return false;
2238 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002239 }
2240 }
2241
2242 return true;
2243}
2244
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002245bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002246 GLint x,
2247 GLint y,
2248 GLsizei width,
2249 GLsizei height,
2250 GLenum format,
2251 GLenum type,
2252 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002253{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002254 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2255}
2256
2257bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2258 GLint x,
2259 GLint y,
2260 GLsizei width,
2261 GLsizei height,
2262 GLenum format,
2263 GLenum type,
2264 GLsizei bufSize,
2265 GLsizei *length,
2266 GLvoid *pixels)
2267{
2268 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002269 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002270 return false;
2271 }
2272
Geoff Lang62fce5b2016-09-30 10:46:35 -04002273 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2274 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002275 {
Geoff Langb1196682014-07-23 13:47:29 -04002276 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002277 }
2278
Geoff Lang62fce5b2016-09-30 10:46:35 -04002279 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002280 {
Geoff Langb1196682014-07-23 13:47:29 -04002281 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002282 }
2283
Jamie Madillc29968b2016-01-20 11:17:23 -05002284 return true;
2285}
2286
2287bool ValidateReadnPixelsEXT(Context *context,
2288 GLint x,
2289 GLint y,
2290 GLsizei width,
2291 GLsizei height,
2292 GLenum format,
2293 GLenum type,
2294 GLsizei bufSize,
2295 GLvoid *pixels)
2296{
2297 if (bufSize < 0)
2298 {
Jamie Madill437fa652016-05-03 15:13:24 -04002299 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002300 return false;
2301 }
2302
Geoff Lang62fce5b2016-09-30 10:46:35 -04002303 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2304 pixels);
2305}
Jamie Madill26e91952014-03-05 15:01:27 -05002306
Geoff Lang62fce5b2016-09-30 10:46:35 -04002307bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2308 GLint x,
2309 GLint y,
2310 GLsizei width,
2311 GLsizei height,
2312 GLenum format,
2313 GLenum type,
2314 GLsizei bufSize,
2315 GLsizei *length,
2316 GLvoid *data)
2317{
2318 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002319 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002320 return false;
2321 }
2322
Geoff Lang62fce5b2016-09-30 10:46:35 -04002323 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002324 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002325 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002326 }
2327
Geoff Lang62fce5b2016-09-30 10:46:35 -04002328 if (!ValidateRobustBufferSize(context, bufSize, *length))
2329 {
2330 return false;
2331 }
2332
2333 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002334}
2335
Olli Etuaho41997e72016-03-10 13:38:39 +02002336bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002337{
2338 if (!context->getExtensions().occlusionQueryBoolean &&
2339 !context->getExtensions().disjointTimerQuery)
2340 {
Jamie Madill437fa652016-05-03 15:13:24 -04002341 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002342 return false;
2343 }
2344
Olli Etuaho41997e72016-03-10 13:38:39 +02002345 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002346}
2347
Olli Etuaho41997e72016-03-10 13:38:39 +02002348bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002349{
2350 if (!context->getExtensions().occlusionQueryBoolean &&
2351 !context->getExtensions().disjointTimerQuery)
2352 {
Jamie Madill437fa652016-05-03 15:13:24 -04002353 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002354 return false;
2355 }
2356
Olli Etuaho41997e72016-03-10 13:38:39 +02002357 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002358}
2359
2360bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002361{
2362 if (!ValidQueryType(context, target))
2363 {
Jamie Madill437fa652016-05-03 15:13:24 -04002364 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002365 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002366 }
2367
2368 if (id == 0)
2369 {
Jamie Madill437fa652016-05-03 15:13:24 -04002370 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002371 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002372 }
2373
2374 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2375 // of zero, if the active query object name for <target> is non-zero (for the
2376 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2377 // the active query for either target is non-zero), if <id> is the name of an
2378 // existing query object whose type does not match <target>, or if <id> is the
2379 // active query object name for any query type, the error INVALID_OPERATION is
2380 // generated.
2381
2382 // Ensure no other queries are active
2383 // NOTE: If other queries than occlusion are supported, we will need to check
2384 // separately that:
2385 // a) The query ID passed is not the current active query for any target/type
2386 // b) There are no active queries for the requested target (and in the case
2387 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2388 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002389
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002390 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002391 {
Jamie Madill437fa652016-05-03 15:13:24 -04002392 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002393 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002394 }
2395
2396 Query *queryObject = context->getQuery(id, true, target);
2397
2398 // check that name was obtained with glGenQueries
2399 if (!queryObject)
2400 {
Jamie Madill437fa652016-05-03 15:13:24 -04002401 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002402 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002403 }
2404
2405 // check for type mismatch
2406 if (queryObject->getType() != target)
2407 {
Jamie Madill437fa652016-05-03 15:13:24 -04002408 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002409 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002410 }
2411
2412 return true;
2413}
2414
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002415bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2416{
2417 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002418 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002419 {
Jamie Madill437fa652016-05-03 15:13:24 -04002420 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002421 return false;
2422 }
2423
2424 return ValidateBeginQueryBase(context, target, id);
2425}
2426
2427bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002428{
2429 if (!ValidQueryType(context, target))
2430 {
Jamie Madill437fa652016-05-03 15:13:24 -04002431 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002432 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002433 }
2434
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002435 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002436
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002437 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002438 {
Jamie Madill437fa652016-05-03 15:13:24 -04002439 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002440 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002441 }
2442
Jamie Madill45c785d2014-05-13 14:09:34 -04002443 return true;
2444}
2445
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002446bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2447{
2448 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002449 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002450 {
Jamie Madill437fa652016-05-03 15:13:24 -04002451 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002452 return false;
2453 }
2454
2455 return ValidateEndQueryBase(context, target);
2456}
2457
2458bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2459{
2460 if (!context->getExtensions().disjointTimerQuery)
2461 {
Jamie Madill437fa652016-05-03 15:13:24 -04002462 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002463 return false;
2464 }
2465
2466 if (target != GL_TIMESTAMP_EXT)
2467 {
Jamie Madill437fa652016-05-03 15:13:24 -04002468 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002469 return false;
2470 }
2471
2472 Query *queryObject = context->getQuery(id, true, target);
2473 if (queryObject == nullptr)
2474 {
Jamie Madill437fa652016-05-03 15:13:24 -04002475 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002476 return false;
2477 }
2478
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002479 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002480 {
Jamie Madill437fa652016-05-03 15:13:24 -04002481 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002482 return false;
2483 }
2484
2485 return true;
2486}
2487
Geoff Lang2186c382016-10-14 10:54:54 -04002488bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002489{
Geoff Lang2186c382016-10-14 10:54:54 -04002490 if (numParams)
2491 {
2492 *numParams = 0;
2493 }
2494
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002495 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2496 {
Jamie Madill437fa652016-05-03 15:13:24 -04002497 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002498 return false;
2499 }
2500
2501 switch (pname)
2502 {
2503 case GL_CURRENT_QUERY_EXT:
2504 if (target == GL_TIMESTAMP_EXT)
2505 {
Jamie Madill437fa652016-05-03 15:13:24 -04002506 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002507 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2508 return false;
2509 }
2510 break;
2511 case GL_QUERY_COUNTER_BITS_EXT:
2512 if (!context->getExtensions().disjointTimerQuery ||
2513 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2514 {
Jamie Madill437fa652016-05-03 15:13:24 -04002515 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002516 return false;
2517 }
2518 break;
2519 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002520 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002521 return false;
2522 }
2523
Geoff Lang2186c382016-10-14 10:54:54 -04002524 if (numParams)
2525 {
2526 // All queries return only one value
2527 *numParams = 1;
2528 }
2529
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002530 return true;
2531}
2532
2533bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2534{
2535 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002536 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002537 {
Jamie Madill437fa652016-05-03 15:13:24 -04002538 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002539 return false;
2540 }
2541
Geoff Lang2186c382016-10-14 10:54:54 -04002542 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002543}
2544
Geoff Lang2186c382016-10-14 10:54:54 -04002545bool ValidateGetQueryivRobustANGLE(Context *context,
2546 GLenum target,
2547 GLenum pname,
2548 GLsizei bufSize,
2549 GLsizei *length,
2550 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002551{
Geoff Lang2186c382016-10-14 10:54:54 -04002552 if (!ValidateRobustEntryPoint(context, bufSize))
2553 {
2554 return false;
2555 }
2556
2557 if (!ValidateGetQueryivBase(context, target, pname, length))
2558 {
2559 return false;
2560 }
2561
2562 if (!ValidateRobustBufferSize(context, bufSize, *length))
2563 {
2564 return false;
2565 }
2566
2567 return true;
2568}
2569
2570bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2571{
2572 if (numParams)
2573 {
2574 *numParams = 0;
2575 }
2576
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002577 Query *queryObject = context->getQuery(id, false, GL_NONE);
2578
2579 if (!queryObject)
2580 {
Jamie Madill437fa652016-05-03 15:13:24 -04002581 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002582 return false;
2583 }
2584
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002585 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002586 {
Jamie Madill437fa652016-05-03 15:13:24 -04002587 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002588 return false;
2589 }
2590
2591 switch (pname)
2592 {
2593 case GL_QUERY_RESULT_EXT:
2594 case GL_QUERY_RESULT_AVAILABLE_EXT:
2595 break;
2596
2597 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002598 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002599 return false;
2600 }
2601
Geoff Lang2186c382016-10-14 10:54:54 -04002602 if (numParams)
2603 {
2604 *numParams = 1;
2605 }
2606
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002607 return true;
2608}
2609
2610bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2611{
2612 if (!context->getExtensions().disjointTimerQuery)
2613 {
Jamie Madill437fa652016-05-03 15:13:24 -04002614 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002615 return false;
2616 }
Geoff Lang2186c382016-10-14 10:54:54 -04002617 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2618}
2619
2620bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2621 GLuint id,
2622 GLenum pname,
2623 GLsizei bufSize,
2624 GLsizei *length,
2625 GLint *params)
2626{
2627 if (!context->getExtensions().disjointTimerQuery)
2628 {
2629 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2630 return false;
2631 }
2632
2633 if (!ValidateRobustEntryPoint(context, bufSize))
2634 {
2635 return false;
2636 }
2637
2638 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2639 {
2640 return false;
2641 }
2642
2643 if (!ValidateRobustBufferSize(context, bufSize, *length))
2644 {
2645 return false;
2646 }
2647
2648 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002649}
2650
2651bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2652{
2653 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002654 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002655 {
Jamie Madill437fa652016-05-03 15:13:24 -04002656 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002657 return false;
2658 }
Geoff Lang2186c382016-10-14 10:54:54 -04002659 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2660}
2661
2662bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2663 GLuint id,
2664 GLenum pname,
2665 GLsizei bufSize,
2666 GLsizei *length,
2667 GLuint *params)
2668{
2669 if (!context->getExtensions().disjointTimerQuery &&
2670 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2671 {
2672 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2673 return false;
2674 }
2675
2676 if (!ValidateRobustEntryPoint(context, bufSize))
2677 {
2678 return false;
2679 }
2680
2681 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2682 {
2683 return false;
2684 }
2685
2686 if (!ValidateRobustBufferSize(context, bufSize, *length))
2687 {
2688 return false;
2689 }
2690
2691 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002692}
2693
2694bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2695{
2696 if (!context->getExtensions().disjointTimerQuery)
2697 {
Jamie Madill437fa652016-05-03 15:13:24 -04002698 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002699 return false;
2700 }
Geoff Lang2186c382016-10-14 10:54:54 -04002701 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2702}
2703
2704bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2705 GLuint id,
2706 GLenum pname,
2707 GLsizei bufSize,
2708 GLsizei *length,
2709 GLint64 *params)
2710{
2711 if (!context->getExtensions().disjointTimerQuery)
2712 {
2713 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2714 return false;
2715 }
2716
2717 if (!ValidateRobustEntryPoint(context, bufSize))
2718 {
2719 return false;
2720 }
2721
2722 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2723 {
2724 return false;
2725 }
2726
2727 if (!ValidateRobustBufferSize(context, bufSize, *length))
2728 {
2729 return false;
2730 }
2731
2732 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002733}
2734
2735bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2736{
2737 if (!context->getExtensions().disjointTimerQuery)
2738 {
Jamie Madill437fa652016-05-03 15:13:24 -04002739 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002740 return false;
2741 }
Geoff Lang2186c382016-10-14 10:54:54 -04002742 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2743}
2744
2745bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2746 GLuint id,
2747 GLenum pname,
2748 GLsizei bufSize,
2749 GLsizei *length,
2750 GLuint64 *params)
2751{
2752 if (!context->getExtensions().disjointTimerQuery)
2753 {
2754 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2755 return false;
2756 }
2757
2758 if (!ValidateRobustEntryPoint(context, bufSize))
2759 {
2760 return false;
2761 }
2762
2763 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2764 {
2765 return false;
2766 }
2767
2768 if (!ValidateRobustBufferSize(context, bufSize, *length))
2769 {
2770 return false;
2771 }
2772
2773 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002774}
2775
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002776bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002777 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002778 GLuint program,
2779 GLint location,
2780 GLsizei count)
2781{
2782 // Check for ES31 program uniform entry points
2783 if (context->getClientVersion() < Version(3, 1))
2784 {
2785 context->handleError(Error(GL_INVALID_OPERATION));
2786 return false;
2787 }
2788
2789 const LinkedUniform *uniform = nullptr;
2790 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002791 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2792 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002793}
2794
Frank Henigmana98a6472017-02-02 21:38:32 -05002795bool ValidateProgramUniform1iv(gl::Context *context,
2796 GLuint program,
2797 GLint location,
2798 GLsizei count,
2799 const GLint *value)
2800{
2801 // Check for ES31 program uniform entry points
2802 if (context->getClientVersion() < Version(3, 1))
2803 {
2804 context->handleError(Error(GL_INVALID_OPERATION));
2805 return false;
2806 }
2807
2808 const LinkedUniform *uniform = nullptr;
2809 gl::Program *programObject = GetValidProgram(context, program);
2810 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2811 ValidateUniform1ivValue(context, uniform->type, count, value);
2812}
2813
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002814bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002815 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002816 GLuint program,
2817 GLint location,
2818 GLsizei count,
2819 GLboolean transpose)
2820{
2821 // Check for ES31 program uniform entry points
2822 if (context->getClientVersion() < Version(3, 1))
2823 {
2824 context->handleError(Error(GL_INVALID_OPERATION));
2825 return false;
2826 }
2827
2828 const LinkedUniform *uniform = nullptr;
2829 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002830 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2831 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002832}
2833
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002834bool ValidateUniform(gl::Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002835{
2836 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002837 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002838 {
Jamie Madill437fa652016-05-03 15:13:24 -04002839 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002840 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002841 }
2842
Jamie Madill62d31cb2015-09-11 13:25:51 -04002843 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002844 gl::Program *programObject = context->getGLState().getProgram();
2845 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2846 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002847}
2848
Frank Henigmana98a6472017-02-02 21:38:32 -05002849bool ValidateUniform1iv(gl::Context *context, GLint location, GLsizei count, const GLint *value)
2850{
2851 const LinkedUniform *uniform = nullptr;
2852 gl::Program *programObject = context->getGLState().getProgram();
2853 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2854 ValidateUniform1ivValue(context, uniform->type, count, value);
2855}
2856
He Yunchaoced53ae2016-11-29 15:00:51 +08002857bool ValidateUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002858 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002859 GLint location,
2860 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002861 GLboolean transpose)
2862{
2863 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002864 int rows = VariableRowCount(valueType);
2865 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002866 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002867 {
Jamie Madill437fa652016-05-03 15:13:24 -04002868 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002869 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002870 }
2871
Martin Radev1be913c2016-07-11 17:59:16 +03002872 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002873 {
Jamie Madill437fa652016-05-03 15:13:24 -04002874 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002875 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002876 }
2877
Jamie Madill62d31cb2015-09-11 13:25:51 -04002878 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002879 gl::Program *programObject = context->getGLState().getProgram();
2880 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2881 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002882}
2883
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002884bool ValidateStateQuery(ValidationContext *context,
2885 GLenum pname,
2886 GLenum *nativeType,
2887 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002888{
2889 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2890 {
Jamie Madill437fa652016-05-03 15:13:24 -04002891 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002892 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002893 }
2894
Jamie Madill0af26e12015-03-05 19:54:33 -05002895 const Caps &caps = context->getCaps();
2896
Jamie Madill893ab082014-05-16 16:56:10 -04002897 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2898 {
2899 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2900
Jamie Madill0af26e12015-03-05 19:54:33 -05002901 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002902 {
Jamie Madill437fa652016-05-03 15:13:24 -04002903 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002904 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002905 }
2906 }
2907
2908 switch (pname)
2909 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002910 case GL_TEXTURE_BINDING_2D:
2911 case GL_TEXTURE_BINDING_CUBE_MAP:
2912 case GL_TEXTURE_BINDING_3D:
2913 case GL_TEXTURE_BINDING_2D_ARRAY:
2914 break;
2915 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2916 if (!context->getExtensions().eglStreamConsumerExternal &&
2917 !context->getExtensions().eglImageExternal)
2918 {
2919 context->handleError(Error(GL_INVALID_ENUM,
2920 "Neither NV_EGL_stream_consumer_external nor "
2921 "GL_OES_EGL_image_external extensions enabled"));
2922 return false;
2923 }
2924 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002925
He Yunchaoced53ae2016-11-29 15:00:51 +08002926 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2927 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002928 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002929 if (context->getGLState().getReadFramebuffer()->checkStatus(
2930 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002931 {
Jamie Madill437fa652016-05-03 15:13:24 -04002932 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002933 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002934 }
2935
Jamie Madill51f40ec2016-06-15 14:06:00 -04002936 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2937 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002938
2939 if (framebuffer->getReadBufferState() == GL_NONE)
2940 {
2941 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2942 return false;
2943 }
2944
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002945 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002946 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002947 {
Jamie Madill437fa652016-05-03 15:13:24 -04002948 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002949 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002950 }
2951 }
2952 break;
2953
He Yunchaoced53ae2016-11-29 15:00:51 +08002954 default:
2955 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002956 }
2957
2958 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002959 if (*numParams == 0)
2960 {
2961 return false;
2962 }
2963
2964 return true;
2965}
2966
2967bool ValidateRobustStateQuery(ValidationContext *context,
2968 GLenum pname,
2969 GLsizei bufSize,
2970 GLenum *nativeType,
2971 unsigned int *numParams)
2972{
2973 if (!ValidateRobustEntryPoint(context, bufSize))
2974 {
2975 return false;
2976 }
2977
2978 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2979 {
2980 return false;
2981 }
2982
2983 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002984 {
2985 return false;
2986 }
2987
2988 return true;
2989}
2990
Jamie Madillc29968b2016-01-20 11:17:23 -05002991bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2992 GLenum target,
2993 GLint level,
2994 GLenum internalformat,
2995 bool isSubImage,
2996 GLint xoffset,
2997 GLint yoffset,
2998 GLint zoffset,
2999 GLint x,
3000 GLint y,
3001 GLsizei width,
3002 GLsizei height,
3003 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04003004 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04003005{
Jamie Madill560a8d82014-05-21 13:06:20 -04003006 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
3007 {
Jamie Madill437fa652016-05-03 15:13:24 -04003008 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003009 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003010 }
3011
He Yunchaoced53ae2016-11-29 15:00:51 +08003012 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3013 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04003014 {
Jamie Madill437fa652016-05-03 15:13:24 -04003015 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003016 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003017 }
3018
3019 if (border != 0)
3020 {
Jamie Madill437fa652016-05-03 15:13:24 -04003021 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003022 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003023 }
3024
3025 if (!ValidMipLevel(context, target, level))
3026 {
Jamie Madill437fa652016-05-03 15:13:24 -04003027 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003028 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003029 }
3030
Jamie Madill51f40ec2016-06-15 14:06:00 -04003031 const auto &state = context->getGLState();
3032 auto readFramebuffer = state.getReadFramebuffer();
3033 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003034 {
Jamie Madill437fa652016-05-03 15:13:24 -04003035 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003036 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003037 }
3038
Jamie Madill51f40ec2016-06-15 14:06:00 -04003039 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003040 {
Jamie Madill437fa652016-05-03 15:13:24 -04003041 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003042 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003043 }
3044
Martin Radev138064f2016-07-15 12:03:41 +03003045 if (readFramebuffer->getReadBufferState() == GL_NONE)
3046 {
3047 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3048 return false;
3049 }
3050
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003051 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3052 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003053 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003054 // situation is an application error that would lead to a crash in ANGLE.
3055 if (readFramebuffer->getReadColorbuffer() == nullptr)
3056 {
3057 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3058 return false;
3059 }
3060
Geoff Langaae65a42014-05-26 12:43:44 -04003061 const gl::Caps &caps = context->getCaps();
3062
Geoff Langaae65a42014-05-26 12:43:44 -04003063 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003064 switch (target)
3065 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003066 case GL_TEXTURE_2D:
3067 maxDimension = caps.max2DTextureSize;
3068 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003069
He Yunchaoced53ae2016-11-29 15:00:51 +08003070 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3071 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3072 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3073 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3074 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3075 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3076 maxDimension = caps.maxCubeMapTextureSize;
3077 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003078
He Yunchaoced53ae2016-11-29 15:00:51 +08003079 case GL_TEXTURE_2D_ARRAY:
3080 maxDimension = caps.max2DTextureSize;
3081 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003082
He Yunchaoced53ae2016-11-29 15:00:51 +08003083 case GL_TEXTURE_3D:
3084 maxDimension = caps.max3DTextureSize;
3085 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003086
He Yunchaoced53ae2016-11-29 15:00:51 +08003087 default:
3088 context->handleError(Error(GL_INVALID_ENUM));
3089 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003090 }
3091
Jamie Madillc29968b2016-01-20 11:17:23 -05003092 gl::Texture *texture =
3093 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003094 if (!texture)
3095 {
Jamie Madill437fa652016-05-03 15:13:24 -04003096 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003097 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003098 }
3099
Geoff Lang69cce582015-09-17 13:20:36 -04003100 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003101 {
Jamie Madill437fa652016-05-03 15:13:24 -04003102 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003103 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003104 }
3105
Geoff Lang5d601382014-07-22 15:14:06 -04003106 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3107
3108 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003109 {
Jamie Madill437fa652016-05-03 15:13:24 -04003110 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003111 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003112 }
3113
Geoff Lang44ff5a72017-02-03 15:15:43 -05003114 if (formatInfo.compressed &&
3115 !ValidCompressedImageSize(context, internalformat, xoffset, yoffset, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003116 {
Jamie Madill437fa652016-05-03 15:13:24 -04003117 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003118 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003119 }
3120
3121 if (isSubImage)
3122 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003123 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3124 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3125 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003126 {
Jamie Madill437fa652016-05-03 15:13:24 -04003127 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003128 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003129 }
3130 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003131 else
3132 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003133 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003134 {
Jamie Madill437fa652016-05-03 15:13:24 -04003135 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003136 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003137 }
3138
Geoff Langeb66a6e2016-10-31 13:06:12 -04003139 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003140 {
Jamie Madill437fa652016-05-03 15:13:24 -04003141 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003142 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003143 }
3144
3145 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003146 if (static_cast<int>(width) > maxLevelDimension ||
3147 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003148 {
Jamie Madill437fa652016-05-03 15:13:24 -04003149 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003150 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003151 }
3152 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003153
Jamie Madill0c8abca2016-07-22 20:21:26 -04003154 if (textureFormatOut)
3155 {
3156 *textureFormatOut = texture->getFormat(target, level);
3157 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003158
3159 // Detect texture copying feedback loops for WebGL.
3160 if (context->getExtensions().webglCompatibility)
3161 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05003162 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05003163 {
3164 context->handleError(Error(GL_INVALID_OPERATION,
3165 "Texture copying feedback loop formed between Framebuffer "
3166 "and specified Texture level."));
3167 return false;
3168 }
3169 }
3170
Jamie Madill560a8d82014-05-21 13:06:20 -04003171 return true;
3172}
3173
Jiajia Qind9671222016-11-29 16:30:31 +08003174bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003175{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003176 switch (mode)
3177 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003178 case GL_POINTS:
3179 case GL_LINES:
3180 case GL_LINE_LOOP:
3181 case GL_LINE_STRIP:
3182 case GL_TRIANGLES:
3183 case GL_TRIANGLE_STRIP:
3184 case GL_TRIANGLE_FAN:
3185 break;
3186 default:
3187 context->handleError(Error(GL_INVALID_ENUM));
3188 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003189 }
3190
Jamie Madill250d33f2014-06-06 17:09:03 -04003191 if (count < 0)
3192 {
Jamie Madill437fa652016-05-03 15:13:24 -04003193 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003194 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003195 }
3196
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003197 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003198
Jamie Madill250d33f2014-06-06 17:09:03 -04003199 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003200 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003201 {
Jamie Madill437fa652016-05-03 15:13:24 -04003202 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003203 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003204 }
3205
Jamie Madillcbcde722017-01-06 14:50:00 -05003206 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3207 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003208 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003209 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3210 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003211 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003212 const FramebufferAttachment *dsAttachment =
3213 framebuffer->getStencilOrDepthStencilAttachment();
3214 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003215 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003216 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003217
3218 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3219 bool differentWritemasks =
3220 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3221 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3222 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3223 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3224
3225 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003226 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003227 if (!context->getExtensions().webglCompatibility)
3228 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003229 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3230 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003231 }
Jamie Madill437fa652016-05-03 15:13:24 -04003232 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003233 return false;
3234 }
Jamie Madillac528012014-06-20 13:21:23 -04003235 }
3236
Jamie Madill51f40ec2016-06-15 14:06:00 -04003237 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003238 {
Jamie Madill437fa652016-05-03 15:13:24 -04003239 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003240 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003241 }
3242
Geoff Lang7dd2e102014-11-10 15:19:26 -05003243 gl::Program *program = state.getProgram();
3244 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003245 {
Jamie Madill437fa652016-05-03 15:13:24 -04003246 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003247 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003248 }
3249
Geoff Lang7dd2e102014-11-10 15:19:26 -05003250 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003251 {
Jamie Madill437fa652016-05-03 15:13:24 -04003252 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003253 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003254 }
3255
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003256 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003257 for (unsigned int uniformBlockIndex = 0;
3258 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003259 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003260 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003261 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003262 const OffsetBindingPointer<Buffer> &uniformBuffer =
3263 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003264
Geoff Lang5d124a62015-09-15 13:03:27 -04003265 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003266 {
3267 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003268 context->handleError(
3269 Error(GL_INVALID_OPERATION,
3270 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003271 return false;
3272 }
3273
Geoff Lang5d124a62015-09-15 13:03:27 -04003274 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003275 if (uniformBufferSize == 0)
3276 {
3277 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003278 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003279 }
3280
Jamie Madill62d31cb2015-09-11 13:25:51 -04003281 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003282 {
3283 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003284 context->handleError(
3285 Error(GL_INVALID_OPERATION,
3286 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003287 return false;
3288 }
3289 }
3290
Jamie Madilla4595b82017-01-11 17:36:34 -05003291 // Detect rendering feedback loops for WebGL.
3292 if (context->getExtensions().webglCompatibility)
3293 {
3294 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3295 {
3296 context->handleError(
3297 Error(GL_INVALID_OPERATION,
3298 "Rendering feedback loop formed between Framebuffer and active Texture."));
3299 return false;
3300 }
3301 }
3302
Jamie Madill250d33f2014-06-06 17:09:03 -04003303 // No-op if zero count
3304 return (count > 0);
3305}
3306
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003307bool ValidateDrawArrays(ValidationContext *context,
3308 GLenum mode,
3309 GLint first,
3310 GLsizei count,
3311 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003312{
Jamie Madillfd716582014-06-06 17:09:04 -04003313 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003314 {
Jamie Madill437fa652016-05-03 15:13:24 -04003315 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003316 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003317 }
3318
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003319 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003320 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003321 if (curTransformFeedback && curTransformFeedback->isActive() &&
3322 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003323 {
3324 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003325 // that does not match the current transform feedback object's draw mode (if transform
3326 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003327 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003328 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003329 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003330 }
3331
Jiajia Qind9671222016-11-29 16:30:31 +08003332 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003333 {
3334 return false;
3335 }
3336
Corentin Wallez71168a02016-12-19 15:11:18 -08003337 // Check the computation of maxVertex doesn't overflow.
3338 // - first < 0 or count < 0 have been checked as an error condition
3339 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3340 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3341 ASSERT(count > 0 && first >= 0);
3342 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3343 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003344 {
3345 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3346 return false;
3347 }
3348
Corentin Wallez71168a02016-12-19 15:11:18 -08003349 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003350 {
3351 return false;
3352 }
3353
3354 return true;
3355}
3356
He Yunchaoced53ae2016-11-29 15:00:51 +08003357bool ValidateDrawArraysInstanced(Context *context,
3358 GLenum mode,
3359 GLint first,
3360 GLsizei count,
3361 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003362{
3363 if (primcount < 0)
3364 {
Jamie Madill437fa652016-05-03 15:13:24 -04003365 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003366 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003367 }
3368
Jamie Madill2b976812014-08-25 15:47:49 -04003369 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003370 {
3371 return false;
3372 }
3373
3374 // No-op if zero primitive count
3375 return (primcount > 0);
3376}
3377
Geoff Lang87a93302014-09-16 13:29:43 -04003378static bool ValidateDrawInstancedANGLE(Context *context)
3379{
3380 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003381 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003382
Geoff Lang7dd2e102014-11-10 15:19:26 -05003383 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003384
3385 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003386 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003387 {
3388 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003389 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003390 {
3391 return true;
3392 }
3393 }
3394
Jamie Madill437fa652016-05-03 15:13:24 -04003395 context->handleError(Error(GL_INVALID_OPERATION,
3396 "ANGLE_instanced_arrays requires that at least one active attribute"
3397 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003398 return false;
3399}
3400
He Yunchaoced53ae2016-11-29 15:00:51 +08003401bool ValidateDrawArraysInstancedANGLE(Context *context,
3402 GLenum mode,
3403 GLint first,
3404 GLsizei count,
3405 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003406{
3407 if (!ValidateDrawInstancedANGLE(context))
3408 {
3409 return false;
3410 }
3411
3412 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3413}
3414
Jiajia Qind9671222016-11-29 16:30:31 +08003415bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003416{
Jamie Madill250d33f2014-06-06 17:09:03 -04003417 switch (type)
3418 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003419 case GL_UNSIGNED_BYTE:
3420 case GL_UNSIGNED_SHORT:
3421 break;
3422 case GL_UNSIGNED_INT:
3423 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3424 {
3425 context->handleError(Error(GL_INVALID_ENUM));
3426 return false;
3427 }
3428 break;
3429 default:
3430 context->handleError(Error(GL_INVALID_ENUM));
3431 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003432 }
3433
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003434 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003435
3436 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003437 if (curTransformFeedback && curTransformFeedback->isActive() &&
3438 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003439 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003440 // It is an invalid operation to call DrawElements, DrawRangeElements or
3441 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003442 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003443 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003444 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003445 }
3446
Jiajia Qind9671222016-11-29 16:30:31 +08003447 return true;
3448}
3449
3450bool ValidateDrawElements(ValidationContext *context,
3451 GLenum mode,
3452 GLsizei count,
3453 GLenum type,
3454 const GLvoid *indices,
3455 GLsizei primcount,
3456 IndexRange *indexRangeOut)
3457{
3458 if (!ValidateDrawElementsBase(context, type))
3459 return false;
3460
3461 const State &state = context->getGLState();
3462
Jamie Madill250d33f2014-06-06 17:09:03 -04003463 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003464 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003465 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003466 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04003467 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003468 }
3469
He Yunchaoced53ae2016-11-29 15:00:51 +08003470 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003471 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003472
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003473 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3474
3475 if (context->getExtensions().webglCompatibility)
3476 {
3477 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3478 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3479 {
3480 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3481 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3482 // data type passed to the call, or an INVALID_OPERATION error is generated.
3483 context->handleError(Error(GL_INVALID_OPERATION,
3484 "indices must be a multiple of the element type size."));
3485 return false;
3486 }
3487 if (!elementArrayBuffer && count > 0)
3488 {
3489 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3490 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3491 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3492 context->handleError(Error(GL_INVALID_OPERATION,
3493 "There is no element array buffer bound and count > 0."));
3494 return false;
3495 }
3496 }
3497
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003498 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003499 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003500 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003501 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003502 GLint64 offset = reinterpret_cast<GLint64>(indices);
3503 GLint64 byteCount =
3504 static_cast<GLint64>(typeBytes) * static_cast<GLint64>(count) + offset;
3505
3506 // check for integer overflows
3507 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeBytes) ||
3508 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3509 {
3510 context->handleError(Error(GL_OUT_OF_MEMORY, "Integer overflow."));
3511 return false;
3512 }
3513
3514 // Check for reading past the end of the bound buffer object
3515 if (byteCount > elementArrayBuffer->getSize())
3516 {
3517 context->handleError(
3518 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
3519 return false;
3520 }
3521 }
3522 else if (!indices)
3523 {
3524 // This is an application error that would normally result in a crash,
3525 // but we catch it and return an error
3526 context->handleError(
3527 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003528 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003529 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003530 }
3531
Jiajia Qind9671222016-11-29 16:30:31 +08003532 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003533 {
3534 return false;
3535 }
3536
Jamie Madill2b976812014-08-25 15:47:49 -04003537 // Use max index to validate if our vertex buffers are large enough for the pull.
3538 // TODO: offer fast path, with disabled index validation.
3539 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3540 if (elementArrayBuffer)
3541 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003542 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003543 Error error =
3544 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3545 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003546 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003547 {
Jamie Madill437fa652016-05-03 15:13:24 -04003548 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003549 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003550 }
3551 }
3552 else
3553 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003554 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003555 }
3556
Jamie Madille79b1e12015-11-04 16:36:37 -05003557 // If we use an index greater than our maximum supported index range, return an error.
3558 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3559 // return an error if possible here.
3560 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3561 {
Jamie Madill437fa652016-05-03 15:13:24 -04003562 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003563 return false;
3564 }
3565
Corentin Wallez92db6942016-12-09 13:10:36 -05003566 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3567 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003568 {
3569 return false;
3570 }
3571
Geoff Lang3edfe032015-09-04 16:38:24 -04003572 // No op if there are no real indices in the index data (all are primitive restart).
3573 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003574}
3575
Geoff Langb1196682014-07-23 13:47:29 -04003576bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003577 GLenum mode,
3578 GLsizei count,
3579 GLenum type,
3580 const GLvoid *indices,
3581 GLsizei primcount,
3582 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003583{
3584 if (primcount < 0)
3585 {
Jamie Madill437fa652016-05-03 15:13:24 -04003586 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003587 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003588 }
3589
Jamie Madill2b976812014-08-25 15:47:49 -04003590 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003591 {
3592 return false;
3593 }
3594
3595 // No-op zero primitive count
3596 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003597}
3598
Geoff Lang3edfe032015-09-04 16:38:24 -04003599bool ValidateDrawElementsInstancedANGLE(Context *context,
3600 GLenum mode,
3601 GLsizei count,
3602 GLenum type,
3603 const GLvoid *indices,
3604 GLsizei primcount,
3605 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003606{
3607 if (!ValidateDrawInstancedANGLE(context))
3608 {
3609 return false;
3610 }
3611
He Yunchaoced53ae2016-11-29 15:00:51 +08003612 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3613 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003614}
3615
He Yunchaoced53ae2016-11-29 15:00:51 +08003616bool ValidateFramebufferTextureBase(Context *context,
3617 GLenum target,
3618 GLenum attachment,
3619 GLuint texture,
3620 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003621{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003622 if (!ValidFramebufferTarget(target))
3623 {
Jamie Madill437fa652016-05-03 15:13:24 -04003624 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003625 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003626 }
3627
3628 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003629 {
3630 return false;
3631 }
3632
Jamie Madill55ec3b12014-07-03 10:38:57 -04003633 if (texture != 0)
3634 {
3635 gl::Texture *tex = context->getTexture(texture);
3636
3637 if (tex == NULL)
3638 {
Jamie Madill437fa652016-05-03 15:13:24 -04003639 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003640 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003641 }
3642
3643 if (level < 0)
3644 {
Jamie Madill437fa652016-05-03 15:13:24 -04003645 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003646 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003647 }
3648 }
3649
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003650 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003651 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003652
Jamie Madill84115c92015-04-23 15:00:07 -04003653 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003654 {
Jamie Madill437fa652016-05-03 15:13:24 -04003655 context->handleError(
3656 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003657 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003658 }
3659
3660 return true;
3661}
3662
He Yunchaoced53ae2016-11-29 15:00:51 +08003663bool ValidateFramebufferTexture2D(Context *context,
3664 GLenum target,
3665 GLenum attachment,
3666 GLenum textarget,
3667 GLuint texture,
3668 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003669{
He Yunchaoced53ae2016-11-29 15:00:51 +08003670 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3671 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003672 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3673 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003674 {
Jamie Madill437fa652016-05-03 15:13:24 -04003675 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003676 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003677 }
3678
3679 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003680 {
3681 return false;
3682 }
3683
Jamie Madill55ec3b12014-07-03 10:38:57 -04003684 if (texture != 0)
3685 {
3686 gl::Texture *tex = context->getTexture(texture);
3687 ASSERT(tex);
3688
Jamie Madill2a6564e2014-07-11 09:53:19 -04003689 const gl::Caps &caps = context->getCaps();
3690
Jamie Madill55ec3b12014-07-03 10:38:57 -04003691 switch (textarget)
3692 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003693 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003694 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003695 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003696 {
Jamie Madill437fa652016-05-03 15:13:24 -04003697 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003698 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003699 }
3700 if (tex->getTarget() != GL_TEXTURE_2D)
3701 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003702 context->handleError(Error(GL_INVALID_OPERATION,
3703 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003704 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003705 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003706 }
3707 break;
3708
He Yunchaoced53ae2016-11-29 15:00:51 +08003709 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3710 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3711 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3712 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3713 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3714 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003715 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003716 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003717 {
Jamie Madill437fa652016-05-03 15:13:24 -04003718 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003719 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003720 }
3721 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3722 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003723 context->handleError(Error(GL_INVALID_OPERATION,
3724 "Textarget must match the texture target type."));
3725 return false;
3726 }
3727 }
3728 break;
3729
3730 case GL_TEXTURE_2D_MULTISAMPLE:
3731 {
3732 if (context->getClientVersion() < ES_3_1)
3733 {
3734 context->handleError(Error(GL_INVALID_OPERATION,
3735 "Texture target requires at least OpenGL ES 3.1."));
3736 return false;
3737 }
3738
3739 if (level != 0)
3740 {
3741 context->handleError(
3742 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
3743 return false;
3744 }
3745 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
3746 {
3747 context->handleError(Error(GL_INVALID_OPERATION,
3748 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003749 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003750 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003751 }
3752 break;
3753
He Yunchaoced53ae2016-11-29 15:00:51 +08003754 default:
3755 context->handleError(Error(GL_INVALID_ENUM));
3756 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003757 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003758
Jamie Madilla3944d42016-07-22 22:13:26 -04003759 const Format &format = tex->getFormat(textarget, level);
3760 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003761 {
Jamie Madill437fa652016-05-03 15:13:24 -04003762 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003763 return false;
3764 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003765 }
3766
Jamie Madill570f7c82014-07-03 10:38:54 -04003767 return true;
3768}
3769
Geoff Langb1196682014-07-23 13:47:29 -04003770bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003771{
3772 if (program == 0)
3773 {
Jamie Madill437fa652016-05-03 15:13:24 -04003774 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003775 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003776 }
3777
Dian Xiang769769a2015-09-09 15:20:08 -07003778 gl::Program *programObject = GetValidProgram(context, program);
3779 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003780 {
3781 return false;
3782 }
3783
Jamie Madill0063c512014-08-25 15:47:53 -04003784 if (!programObject || !programObject->isLinked())
3785 {
Jamie Madill437fa652016-05-03 15:13:24 -04003786 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003787 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003788 }
3789
Geoff Lang7dd2e102014-11-10 15:19:26 -05003790 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003791 {
Jamie Madill437fa652016-05-03 15:13:24 -04003792 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003793 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003794 }
3795
Jamie Madill0063c512014-08-25 15:47:53 -04003796 return true;
3797}
3798
He Yunchaoced53ae2016-11-29 15:00:51 +08003799bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003800{
3801 return ValidateGetUniformBase(context, program, location);
3802}
3803
He Yunchaoced53ae2016-11-29 15:00:51 +08003804bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003805{
Jamie Madill78f41802014-08-25 15:47:55 -04003806 return ValidateGetUniformBase(context, program, location);
3807}
3808
Geoff Langf41d0ee2016-10-07 13:04:23 -04003809static bool ValidateSizedGetUniform(Context *context,
3810 GLuint program,
3811 GLint location,
3812 GLsizei bufSize,
3813 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003814{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003815 if (length)
3816 {
3817 *length = 0;
3818 }
3819
Jamie Madill78f41802014-08-25 15:47:55 -04003820 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003821 {
Jamie Madill78f41802014-08-25 15:47:55 -04003822 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003823 }
3824
Geoff Langf41d0ee2016-10-07 13:04:23 -04003825 if (bufSize < 0)
3826 {
3827 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3828 return false;
3829 }
3830
Jamie Madilla502c742014-08-28 17:19:13 -04003831 gl::Program *programObject = context->getProgram(program);
3832 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003833
Jamie Madill78f41802014-08-25 15:47:55 -04003834 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003835 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003836 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003837 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003838 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003839 context->handleError(
3840 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003841 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003842 }
3843
Geoff Langf41d0ee2016-10-07 13:04:23 -04003844 if (length)
3845 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003846 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003847 }
3848
Jamie Madill0063c512014-08-25 15:47:53 -04003849 return true;
3850}
3851
He Yunchaoced53ae2016-11-29 15:00:51 +08003852bool ValidateGetnUniformfvEXT(Context *context,
3853 GLuint program,
3854 GLint location,
3855 GLsizei bufSize,
3856 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003857{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003858 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003859}
3860
He Yunchaoced53ae2016-11-29 15:00:51 +08003861bool ValidateGetnUniformivEXT(Context *context,
3862 GLuint program,
3863 GLint location,
3864 GLsizei bufSize,
3865 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003866{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003867 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3868}
3869
3870bool ValidateGetUniformfvRobustANGLE(Context *context,
3871 GLuint program,
3872 GLint location,
3873 GLsizei bufSize,
3874 GLsizei *length,
3875 GLfloat *params)
3876{
3877 if (!ValidateRobustEntryPoint(context, bufSize))
3878 {
3879 return false;
3880 }
3881
3882 // bufSize is validated in ValidateSizedGetUniform
3883 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3884}
3885
3886bool ValidateGetUniformivRobustANGLE(Context *context,
3887 GLuint program,
3888 GLint location,
3889 GLsizei bufSize,
3890 GLsizei *length,
3891 GLint *params)
3892{
3893 if (!ValidateRobustEntryPoint(context, bufSize))
3894 {
3895 return false;
3896 }
3897
3898 // bufSize is validated in ValidateSizedGetUniform
3899 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3900}
3901
3902bool ValidateGetUniformuivRobustANGLE(Context *context,
3903 GLuint program,
3904 GLint location,
3905 GLsizei bufSize,
3906 GLsizei *length,
3907 GLuint *params)
3908{
3909 if (!ValidateRobustEntryPoint(context, bufSize))
3910 {
3911 return false;
3912 }
3913
3914 if (context->getClientMajorVersion() < 3)
3915 {
3916 context->handleError(
3917 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3918 return false;
3919 }
3920
3921 // bufSize is validated in ValidateSizedGetUniform
3922 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003923}
3924
He Yunchaoced53ae2016-11-29 15:00:51 +08003925bool ValidateDiscardFramebufferBase(Context *context,
3926 GLenum target,
3927 GLsizei numAttachments,
3928 const GLenum *attachments,
3929 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003930{
3931 if (numAttachments < 0)
3932 {
Jamie Madill437fa652016-05-03 15:13:24 -04003933 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003934 return false;
3935 }
3936
3937 for (GLsizei i = 0; i < numAttachments; ++i)
3938 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003939 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003940 {
3941 if (defaultFramebuffer)
3942 {
Jamie Madill437fa652016-05-03 15:13:24 -04003943 context->handleError(Error(
3944 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003945 return false;
3946 }
3947
3948 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3949 {
Jamie Madill437fa652016-05-03 15:13:24 -04003950 context->handleError(Error(GL_INVALID_OPERATION,
3951 "Requested color attachment is greater than the maximum "
3952 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003953 return false;
3954 }
3955 }
3956 else
3957 {
3958 switch (attachments[i])
3959 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003960 case GL_DEPTH_ATTACHMENT:
3961 case GL_STENCIL_ATTACHMENT:
3962 case GL_DEPTH_STENCIL_ATTACHMENT:
3963 if (defaultFramebuffer)
3964 {
3965 context->handleError(
3966 Error(GL_INVALID_ENUM,
3967 "Invalid attachment when the default framebuffer is bound"));
3968 return false;
3969 }
3970 break;
3971 case GL_COLOR:
3972 case GL_DEPTH:
3973 case GL_STENCIL:
3974 if (!defaultFramebuffer)
3975 {
3976 context->handleError(
3977 Error(GL_INVALID_ENUM,
3978 "Invalid attachment when the default framebuffer is not bound"));
3979 return false;
3980 }
3981 break;
3982 default:
3983 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003984 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003985 }
3986 }
3987 }
3988
3989 return true;
3990}
3991
Austin Kinross6ee1e782015-05-29 17:05:37 -07003992bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3993{
3994 // Note that debug marker calls must not set error state
3995
3996 if (length < 0)
3997 {
3998 return false;
3999 }
4000
4001 if (marker == nullptr)
4002 {
4003 return false;
4004 }
4005
4006 return true;
4007}
4008
4009bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
4010{
4011 // Note that debug marker calls must not set error state
4012
4013 if (length < 0)
4014 {
4015 return false;
4016 }
4017
4018 if (length > 0 && marker == nullptr)
4019 {
4020 return false;
4021 }
4022
4023 return true;
4024}
4025
Geoff Langdcab33b2015-07-21 13:03:16 -04004026bool ValidateEGLImageTargetTexture2DOES(Context *context,
4027 egl::Display *display,
4028 GLenum target,
4029 egl::Image *image)
4030{
Geoff Langa8406172015-07-21 16:53:39 -04004031 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4032 {
Jamie Madill437fa652016-05-03 15:13:24 -04004033 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004034 return false;
4035 }
4036
4037 switch (target)
4038 {
4039 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004040 if (!context->getExtensions().eglImage)
4041 {
4042 context->handleError(Error(
4043 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4044 }
4045 break;
4046
4047 case GL_TEXTURE_EXTERNAL_OES:
4048 if (!context->getExtensions().eglImageExternal)
4049 {
4050 context->handleError(Error(
4051 GL_INVALID_ENUM,
4052 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4053 }
Geoff Langa8406172015-07-21 16:53:39 -04004054 break;
4055
4056 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004057 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004058 return false;
4059 }
4060
4061 if (!display->isValidImage(image))
4062 {
Jamie Madill437fa652016-05-03 15:13:24 -04004063 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004064 return false;
4065 }
4066
4067 if (image->getSamples() > 0)
4068 {
Jamie Madill437fa652016-05-03 15:13:24 -04004069 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004070 "cannot create a 2D texture from a multisampled EGL image."));
4071 return false;
4072 }
4073
Jamie Madilla3944d42016-07-22 22:13:26 -04004074 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004075 if (!textureCaps.texturable)
4076 {
Jamie Madill437fa652016-05-03 15:13:24 -04004077 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004078 "EGL image internal format is not supported as a texture."));
4079 return false;
4080 }
4081
Geoff Langdcab33b2015-07-21 13:03:16 -04004082 return true;
4083}
4084
4085bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4086 egl::Display *display,
4087 GLenum target,
4088 egl::Image *image)
4089{
Geoff Langa8406172015-07-21 16:53:39 -04004090 if (!context->getExtensions().eglImage)
4091 {
Jamie Madill437fa652016-05-03 15:13:24 -04004092 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004093 return false;
4094 }
4095
4096 switch (target)
4097 {
4098 case GL_RENDERBUFFER:
4099 break;
4100
4101 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004102 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004103 return false;
4104 }
4105
4106 if (!display->isValidImage(image))
4107 {
Jamie Madill437fa652016-05-03 15:13:24 -04004108 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004109 return false;
4110 }
4111
Jamie Madilla3944d42016-07-22 22:13:26 -04004112 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004113 if (!textureCaps.renderable)
4114 {
Jamie Madill437fa652016-05-03 15:13:24 -04004115 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004116 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4117 return false;
4118 }
4119
Geoff Langdcab33b2015-07-21 13:03:16 -04004120 return true;
4121}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004122
4123bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4124{
Geoff Lang36167ab2015-12-07 10:27:14 -05004125 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004126 {
4127 // The default VAO should always exist
4128 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004129 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004130 return false;
4131 }
4132
4133 return true;
4134}
4135
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004136bool ValidateLinkProgram(Context *context, GLuint program)
4137{
4138 if (context->hasActiveTransformFeedback(program))
4139 {
4140 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004141 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004142 "Cannot link program while program is associated with an active "
4143 "transform feedback object."));
4144 return false;
4145 }
4146 return true;
4147}
4148
Geoff Langc5629752015-12-07 16:29:04 -05004149bool ValidateProgramBinaryBase(Context *context,
4150 GLuint program,
4151 GLenum binaryFormat,
4152 const void *binary,
4153 GLint length)
4154{
4155 Program *programObject = GetValidProgram(context, program);
4156 if (programObject == nullptr)
4157 {
4158 return false;
4159 }
4160
4161 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4162 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4163 programBinaryFormats.end())
4164 {
Jamie Madill437fa652016-05-03 15:13:24 -04004165 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004166 return false;
4167 }
4168
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004169 if (context->hasActiveTransformFeedback(program))
4170 {
4171 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004172 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004173 "Cannot change program binary while program is associated with "
4174 "an active transform feedback object."));
4175 return false;
4176 }
4177
Geoff Langc5629752015-12-07 16:29:04 -05004178 return true;
4179}
4180
4181bool ValidateGetProgramBinaryBase(Context *context,
4182 GLuint program,
4183 GLsizei bufSize,
4184 GLsizei *length,
4185 GLenum *binaryFormat,
4186 void *binary)
4187{
4188 Program *programObject = GetValidProgram(context, program);
4189 if (programObject == nullptr)
4190 {
4191 return false;
4192 }
4193
4194 if (!programObject->isLinked())
4195 {
Jamie Madill437fa652016-05-03 15:13:24 -04004196 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004197 return false;
4198 }
4199
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004200 if (context->getCaps().programBinaryFormats.empty())
4201 {
4202 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4203 return false;
4204 }
4205
Geoff Langc5629752015-12-07 16:29:04 -05004206 return true;
4207}
Jamie Madillc29968b2016-01-20 11:17:23 -05004208
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004209bool ValidateUseProgram(Context *context, GLuint program)
4210{
4211 if (program != 0)
4212 {
4213 Program *programObject = context->getProgram(program);
4214 if (!programObject)
4215 {
4216 // ES 3.1.0 section 7.3 page 72
4217 if (context->getShader(program))
4218 {
Jamie Madill437fa652016-05-03 15:13:24 -04004219 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004220 Error(GL_INVALID_OPERATION,
4221 "Attempted to use a single shader instead of a shader program."));
4222 return false;
4223 }
4224 else
4225 {
Jamie Madill437fa652016-05-03 15:13:24 -04004226 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004227 return false;
4228 }
4229 }
4230 if (!programObject->isLinked())
4231 {
Jamie Madill437fa652016-05-03 15:13:24 -04004232 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004233 return false;
4234 }
4235 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004236 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004237 {
4238 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004239 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004240 Error(GL_INVALID_OPERATION,
4241 "Cannot change active program while transform feedback is unpaused."));
4242 return false;
4243 }
4244
4245 return true;
4246}
4247
Jamie Madillc29968b2016-01-20 11:17:23 -05004248bool ValidateCopyTexImage2D(ValidationContext *context,
4249 GLenum target,
4250 GLint level,
4251 GLenum internalformat,
4252 GLint x,
4253 GLint y,
4254 GLsizei width,
4255 GLsizei height,
4256 GLint border)
4257{
Martin Radev1be913c2016-07-11 17:59:16 +03004258 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004259 {
4260 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4261 0, x, y, width, height, border);
4262 }
4263
Martin Radev1be913c2016-07-11 17:59:16 +03004264 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004265 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4266 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004267}
Jamie Madillc29968b2016-01-20 11:17:23 -05004268
4269bool ValidateFramebufferRenderbuffer(Context *context,
4270 GLenum target,
4271 GLenum attachment,
4272 GLenum renderbuffertarget,
4273 GLuint renderbuffer)
4274{
4275 if (!ValidFramebufferTarget(target) ||
4276 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4277 {
Jamie Madill437fa652016-05-03 15:13:24 -04004278 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004279 return false;
4280 }
4281
4282 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4283 renderbuffertarget, renderbuffer);
4284}
4285
4286bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4287{
4288 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4289 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4290 {
Jamie Madill437fa652016-05-03 15:13:24 -04004291 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004292 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4293 return false;
4294 }
4295
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004296 ASSERT(context->getGLState().getDrawFramebuffer());
4297 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004298 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4299
4300 // This should come first before the check for the default frame buffer
4301 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4302 // rather than INVALID_OPERATION
4303 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4304 {
4305 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4306
4307 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004308 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4309 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004310 {
4311 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004312 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4313 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4314 // 3.1 is still a bit ambiguous about the error, but future specs are
4315 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004316 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004317 return false;
4318 }
4319 else if (bufs[colorAttachment] >= maxColorAttachment)
4320 {
Jamie Madill437fa652016-05-03 15:13:24 -04004321 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004322 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004323 return false;
4324 }
4325 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4326 frameBufferId != 0)
4327 {
4328 // INVALID_OPERATION-GL is bound to buffer and ith argument
4329 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004330 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004331 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4332 return false;
4333 }
4334 }
4335
4336 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4337 // and n is not 1 or bufs is bound to value other than BACK and NONE
4338 if (frameBufferId == 0)
4339 {
4340 if (n != 1)
4341 {
Jamie Madill437fa652016-05-03 15:13:24 -04004342 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004343 "n must be 1 when GL is bound to the default framebuffer"));
4344 return false;
4345 }
4346
4347 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4348 {
Jamie Madill437fa652016-05-03 15:13:24 -04004349 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004350 GL_INVALID_OPERATION,
4351 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4352 return false;
4353 }
4354 }
4355
4356 return true;
4357}
4358
4359bool ValidateCopyTexSubImage2D(Context *context,
4360 GLenum target,
4361 GLint level,
4362 GLint xoffset,
4363 GLint yoffset,
4364 GLint x,
4365 GLint y,
4366 GLsizei width,
4367 GLsizei height)
4368{
Martin Radev1be913c2016-07-11 17:59:16 +03004369 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004370 {
4371 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4372 yoffset, x, y, width, height, 0);
4373 }
4374
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004375 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4376 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004377}
4378
Geoff Lang496c02d2016-10-20 11:38:11 -07004379bool ValidateGetBufferPointervBase(Context *context,
4380 GLenum target,
4381 GLenum pname,
4382 GLsizei *length,
4383 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004384{
Geoff Lang496c02d2016-10-20 11:38:11 -07004385 if (length)
4386 {
4387 *length = 0;
4388 }
4389
4390 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4391 {
4392 context->handleError(
4393 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004394 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004395 return false;
4396 }
4397
Olli Etuaho4f667482016-03-30 15:56:35 +03004398 if (!ValidBufferTarget(context, target))
4399 {
Jamie Madill437fa652016-05-03 15:13:24 -04004400 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004401 return false;
4402 }
4403
Geoff Lang496c02d2016-10-20 11:38:11 -07004404 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004405 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004406 case GL_BUFFER_MAP_POINTER:
4407 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004408
Geoff Lang496c02d2016-10-20 11:38:11 -07004409 default:
4410 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4411 return false;
4412 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004413
4414 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4415 // target bound to zero generate an INVALID_OPERATION error."
4416 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004417 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004418 {
Jamie Madill437fa652016-05-03 15:13:24 -04004419 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004420 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4421 return false;
4422 }
4423
Geoff Lang496c02d2016-10-20 11:38:11 -07004424 if (length)
4425 {
4426 *length = 1;
4427 }
4428
Olli Etuaho4f667482016-03-30 15:56:35 +03004429 return true;
4430}
4431
4432bool ValidateUnmapBufferBase(Context *context, GLenum target)
4433{
4434 if (!ValidBufferTarget(context, target))
4435 {
Jamie Madill437fa652016-05-03 15:13:24 -04004436 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004437 return false;
4438 }
4439
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004440 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004441
4442 if (buffer == nullptr || !buffer->isMapped())
4443 {
Jamie Madill437fa652016-05-03 15:13:24 -04004444 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004445 return false;
4446 }
4447
4448 return true;
4449}
4450
4451bool ValidateMapBufferRangeBase(Context *context,
4452 GLenum target,
4453 GLintptr offset,
4454 GLsizeiptr length,
4455 GLbitfield access)
4456{
4457 if (!ValidBufferTarget(context, target))
4458 {
Jamie Madill437fa652016-05-03 15:13:24 -04004459 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004460 return false;
4461 }
4462
4463 if (offset < 0 || length < 0)
4464 {
Jamie Madill437fa652016-05-03 15:13:24 -04004465 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004466 return false;
4467 }
4468
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004469 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004470
4471 if (!buffer)
4472 {
Jamie Madill437fa652016-05-03 15:13:24 -04004473 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004474 return false;
4475 }
4476
4477 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004478 CheckedNumeric<size_t> checkedOffset(offset);
4479 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004480
Jamie Madille2e406c2016-06-02 13:04:10 -04004481 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004482 {
Jamie Madill437fa652016-05-03 15:13:24 -04004483 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004484 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4485 return false;
4486 }
4487
4488 // Check for invalid bits in the mask
4489 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4490 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4491 GL_MAP_UNSYNCHRONIZED_BIT;
4492
4493 if (access & ~(allAccessBits))
4494 {
Jamie Madill437fa652016-05-03 15:13:24 -04004495 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004496 return false;
4497 }
4498
4499 if (length == 0)
4500 {
Jamie Madill437fa652016-05-03 15:13:24 -04004501 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004502 return false;
4503 }
4504
4505 if (buffer->isMapped())
4506 {
Jamie Madill437fa652016-05-03 15:13:24 -04004507 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004508 return false;
4509 }
4510
4511 // Check for invalid bit combinations
4512 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4513 {
Jamie Madill437fa652016-05-03 15:13:24 -04004514 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004515 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4516 return false;
4517 }
4518
4519 GLbitfield writeOnlyBits =
4520 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4521
4522 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4523 {
Jamie Madill437fa652016-05-03 15:13:24 -04004524 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004525 "Invalid access bits when mapping buffer for reading: 0x%X.",
4526 access));
4527 return false;
4528 }
4529
4530 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4531 {
Jamie Madill437fa652016-05-03 15:13:24 -04004532 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004533 GL_INVALID_OPERATION,
4534 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4535 return false;
4536 }
4537 return true;
4538}
4539
4540bool ValidateFlushMappedBufferRangeBase(Context *context,
4541 GLenum target,
4542 GLintptr offset,
4543 GLsizeiptr length)
4544{
4545 if (offset < 0 || length < 0)
4546 {
Jamie Madill437fa652016-05-03 15:13:24 -04004547 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004548 return false;
4549 }
4550
4551 if (!ValidBufferTarget(context, target))
4552 {
Jamie Madill437fa652016-05-03 15:13:24 -04004553 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004554 return false;
4555 }
4556
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004557 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004558
4559 if (buffer == nullptr)
4560 {
Jamie Madill437fa652016-05-03 15:13:24 -04004561 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004562 return false;
4563 }
4564
4565 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4566 {
Jamie Madill437fa652016-05-03 15:13:24 -04004567 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004568 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4569 return false;
4570 }
4571
4572 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004573 CheckedNumeric<size_t> checkedOffset(offset);
4574 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004575
Jamie Madille2e406c2016-06-02 13:04:10 -04004576 if (!checkedSize.IsValid() ||
4577 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004578 {
Jamie Madill437fa652016-05-03 15:13:24 -04004579 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004580 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4581 return false;
4582 }
4583
4584 return true;
4585}
4586
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004587bool ValidateGenerateMipmap(Context *context, GLenum target)
4588{
4589 if (!ValidTextureTarget(context, target))
4590 {
4591 context->handleError(Error(GL_INVALID_ENUM));
4592 return false;
4593 }
4594
4595 Texture *texture = context->getTargetTexture(target);
4596
4597 if (texture == nullptr)
4598 {
4599 context->handleError(Error(GL_INVALID_OPERATION));
4600 return false;
4601 }
4602
4603 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4604
4605 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4606 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4607 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4608 {
4609 context->handleError(Error(GL_INVALID_OPERATION));
4610 return false;
4611 }
4612
Jamie Madilla3944d42016-07-22 22:13:26 -04004613 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4614 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4615 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004616
4617 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4618 // unsized formats or that are color renderable and filterable. Since we do not track if
4619 // the texture was created with sized or unsized format (only sized formats are stored),
4620 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4621 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4622 // textures since they're the only texture format that can be created with unsized formats
4623 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4624 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004625 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4626 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004627 {
4628 context->handleError(Error(GL_INVALID_OPERATION));
4629 return false;
4630 }
4631
4632 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004633 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004634 {
4635 context->handleError(Error(GL_INVALID_OPERATION));
4636 return false;
4637 }
4638
4639 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004640 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004641 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4642 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4643 {
Geoff Lang55482a12016-11-21 16:54:01 -05004644 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004645 context->handleError(Error(GL_INVALID_OPERATION));
4646 return false;
4647 }
4648
4649 // Cube completeness check
4650 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4651 {
4652 context->handleError(Error(GL_INVALID_OPERATION));
4653 return false;
4654 }
4655
4656 return true;
4657}
4658
Olli Etuaho41997e72016-03-10 13:38:39 +02004659bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4660{
4661 return ValidateGenOrDelete(context, n);
4662}
4663
4664bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4665{
4666 return ValidateGenOrDelete(context, n);
4667}
4668
4669bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4670{
4671 return ValidateGenOrDelete(context, n);
4672}
4673
4674bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4675{
4676 return ValidateGenOrDelete(context, n);
4677}
4678
4679bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4680{
4681 return ValidateGenOrDelete(context, n);
4682}
4683
4684bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4685{
4686 return ValidateGenOrDelete(context, n);
4687}
4688
4689bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4690{
4691 return ValidateGenOrDelete(context, n);
4692}
4693
4694bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4695{
4696 return ValidateGenOrDelete(context, n);
4697}
4698
4699bool ValidateGenOrDelete(Context *context, GLint n)
4700{
4701 if (n < 0)
4702 {
Jamie Madill437fa652016-05-03 15:13:24 -04004703 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004704 return false;
4705 }
4706 return true;
4707}
4708
Geoff Langf41a7152016-09-19 15:11:17 -04004709bool ValidateEnable(Context *context, GLenum cap)
4710{
4711 if (!ValidCap(context, cap, false))
4712 {
4713 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4714 return false;
4715 }
4716
4717 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4718 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4719 {
4720 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4721 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4722
4723 // We also output an error message to the debugger window if tracing is active, so that
4724 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05004725 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04004726 return false;
4727 }
4728
4729 return true;
4730}
4731
4732bool ValidateDisable(Context *context, GLenum cap)
4733{
4734 if (!ValidCap(context, cap, false))
4735 {
4736 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4737 return false;
4738 }
4739
4740 return true;
4741}
4742
4743bool ValidateIsEnabled(Context *context, GLenum cap)
4744{
4745 if (!ValidCap(context, cap, true))
4746 {
4747 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4748 return false;
4749 }
4750
4751 return true;
4752}
4753
Geoff Langff5b2d52016-09-07 11:32:23 -04004754bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4755{
4756 if (!context->getExtensions().robustClientMemory)
4757 {
4758 context->handleError(
4759 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4760 return false;
4761 }
4762
4763 if (bufSize < 0)
4764 {
4765 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4766 return false;
4767 }
4768
4769 return true;
4770}
4771
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004772bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4773{
4774 if (bufSize < numParams)
4775 {
4776 context->handleError(Error(GL_INVALID_OPERATION,
4777 "%u parameters are required but %i were provided.", numParams,
4778 bufSize));
4779 return false;
4780 }
4781
4782 return true;
4783}
4784
Geoff Langff5b2d52016-09-07 11:32:23 -04004785bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4786 GLenum target,
4787 GLenum attachment,
4788 GLenum pname,
4789 GLsizei *numParams)
4790{
4791 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4792 *numParams = 1;
4793
4794 if (!ValidFramebufferTarget(target))
4795 {
4796 context->handleError(Error(GL_INVALID_ENUM));
4797 return false;
4798 }
4799
4800 int clientVersion = context->getClientMajorVersion();
4801
4802 switch (pname)
4803 {
4804 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4805 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4806 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4807 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4808 break;
4809
4810 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4811 if (clientVersion < 3 && !context->getExtensions().sRGB)
4812 {
4813 context->handleError(Error(GL_INVALID_ENUM));
4814 return false;
4815 }
4816 break;
4817
4818 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4819 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4820 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4821 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4822 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4823 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4824 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4825 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4826 if (clientVersion < 3)
4827 {
4828 context->handleError(Error(GL_INVALID_ENUM));
4829 return false;
4830 }
4831 break;
4832
4833 default:
4834 context->handleError(Error(GL_INVALID_ENUM));
4835 return false;
4836 }
4837
4838 // Determine if the attachment is a valid enum
4839 switch (attachment)
4840 {
4841 case GL_BACK:
4842 case GL_FRONT:
4843 case GL_DEPTH:
4844 case GL_STENCIL:
4845 case GL_DEPTH_STENCIL_ATTACHMENT:
4846 if (clientVersion < 3)
4847 {
4848 context->handleError(Error(GL_INVALID_ENUM));
4849 return false;
4850 }
4851 break;
4852
4853 case GL_DEPTH_ATTACHMENT:
4854 case GL_STENCIL_ATTACHMENT:
4855 break;
4856
4857 default:
4858 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4859 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4860 {
4861 context->handleError(Error(GL_INVALID_ENUM));
4862 return false;
4863 }
4864 break;
4865 }
4866
4867 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4868 ASSERT(framebuffer);
4869
4870 if (framebuffer->id() == 0)
4871 {
4872 if (clientVersion < 3)
4873 {
4874 context->handleError(Error(GL_INVALID_OPERATION));
4875 return false;
4876 }
4877
4878 switch (attachment)
4879 {
4880 case GL_BACK:
4881 case GL_DEPTH:
4882 case GL_STENCIL:
4883 break;
4884
4885 default:
4886 context->handleError(Error(GL_INVALID_OPERATION));
4887 return false;
4888 }
4889 }
4890 else
4891 {
4892 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4893 {
4894 // Valid attachment query
4895 }
4896 else
4897 {
4898 switch (attachment)
4899 {
4900 case GL_DEPTH_ATTACHMENT:
4901 case GL_STENCIL_ATTACHMENT:
4902 break;
4903
4904 case GL_DEPTH_STENCIL_ATTACHMENT:
4905 if (!framebuffer->hasValidDepthStencil())
4906 {
4907 context->handleError(Error(GL_INVALID_OPERATION));
4908 return false;
4909 }
4910 break;
4911
4912 default:
4913 context->handleError(Error(GL_INVALID_OPERATION));
4914 return false;
4915 }
4916 }
4917 }
4918
4919 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4920 if (attachmentObject)
4921 {
4922 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4923 attachmentObject->type() == GL_TEXTURE ||
4924 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4925
4926 switch (pname)
4927 {
4928 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4929 if (attachmentObject->type() != GL_RENDERBUFFER &&
4930 attachmentObject->type() != GL_TEXTURE)
4931 {
4932 context->handleError(Error(GL_INVALID_ENUM));
4933 return false;
4934 }
4935 break;
4936
4937 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4938 if (attachmentObject->type() != GL_TEXTURE)
4939 {
4940 context->handleError(Error(GL_INVALID_ENUM));
4941 return false;
4942 }
4943 break;
4944
4945 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4946 if (attachmentObject->type() != GL_TEXTURE)
4947 {
4948 context->handleError(Error(GL_INVALID_ENUM));
4949 return false;
4950 }
4951 break;
4952
4953 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4954 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4955 {
4956 context->handleError(Error(GL_INVALID_OPERATION));
4957 return false;
4958 }
4959 break;
4960
4961 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4962 if (attachmentObject->type() != GL_TEXTURE)
4963 {
4964 context->handleError(Error(GL_INVALID_ENUM));
4965 return false;
4966 }
4967 break;
4968
4969 default:
4970 break;
4971 }
4972 }
4973 else
4974 {
4975 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4976 // is NONE, then querying any other pname will generate INVALID_ENUM.
4977
4978 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4979 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4980 // INVALID_OPERATION for all other pnames
4981
4982 switch (pname)
4983 {
4984 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4985 break;
4986
4987 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4988 if (clientVersion < 3)
4989 {
4990 context->handleError(Error(GL_INVALID_ENUM));
4991 return false;
4992 }
4993 break;
4994
4995 default:
4996 if (clientVersion < 3)
4997 {
4998 context->handleError(Error(GL_INVALID_ENUM));
4999 return false;
5000 }
5001 else
5002 {
5003 context->handleError(Error(GL_INVALID_OPERATION));
5004 return false;
5005 }
5006 }
5007 }
5008
5009 return true;
5010}
5011
5012bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5013 GLenum target,
5014 GLenum attachment,
5015 GLenum pname,
5016 GLsizei bufSize,
5017 GLsizei *numParams)
5018{
5019 if (!ValidateRobustEntryPoint(context, bufSize))
5020 {
5021 return false;
5022 }
5023
5024 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5025 {
5026 return false;
5027 }
5028
5029 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5030 {
5031 return false;
5032 }
5033
5034 return true;
5035}
5036
5037bool ValidateGetBufferParameteriv(ValidationContext *context,
5038 GLenum target,
5039 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005040 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005041{
Geoff Langebebe1c2016-10-14 12:01:31 -04005042 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005043}
5044
5045bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5046 GLenum target,
5047 GLenum pname,
5048 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005049 GLsizei *length,
5050 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005051{
5052 if (!ValidateRobustEntryPoint(context, bufSize))
5053 {
5054 return false;
5055 }
5056
Geoff Langebebe1c2016-10-14 12:01:31 -04005057 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005058 {
5059 return false;
5060 }
5061
Geoff Langebebe1c2016-10-14 12:01:31 -04005062 if (!ValidateRobustBufferSize(context, bufSize, *length))
5063 {
5064 return false;
5065 }
5066
5067 return true;
5068}
5069
5070bool ValidateGetBufferParameteri64v(ValidationContext *context,
5071 GLenum target,
5072 GLenum pname,
5073 GLint64 *params)
5074{
5075 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5076}
5077
5078bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5079 GLenum target,
5080 GLenum pname,
5081 GLsizei bufSize,
5082 GLsizei *length,
5083 GLint64 *params)
5084{
5085 if (!ValidateRobustEntryPoint(context, bufSize))
5086 {
5087 return false;
5088 }
5089
5090 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5091 {
5092 return false;
5093 }
5094
5095 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005096 {
5097 return false;
5098 }
5099
5100 return true;
5101}
5102
5103bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5104{
5105 // Currently, all GetProgramiv queries return 1 parameter
5106 *numParams = 1;
5107
5108 Program *programObject = GetValidProgram(context, program);
5109 if (!programObject)
5110 {
5111 return false;
5112 }
5113
5114 switch (pname)
5115 {
5116 case GL_DELETE_STATUS:
5117 case GL_LINK_STATUS:
5118 case GL_VALIDATE_STATUS:
5119 case GL_INFO_LOG_LENGTH:
5120 case GL_ATTACHED_SHADERS:
5121 case GL_ACTIVE_ATTRIBUTES:
5122 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5123 case GL_ACTIVE_UNIFORMS:
5124 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5125 break;
5126
5127 case GL_PROGRAM_BINARY_LENGTH:
5128 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5129 {
5130 context->handleError(Error(GL_INVALID_ENUM,
5131 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5132 "GL_OES_get_program_binary or ES 3.0."));
5133 return false;
5134 }
5135 break;
5136
5137 case GL_ACTIVE_UNIFORM_BLOCKS:
5138 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5139 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5140 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5141 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5142 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5143 if (context->getClientMajorVersion() < 3)
5144 {
5145 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5146 return false;
5147 }
5148 break;
5149
5150 default:
5151 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5152 return false;
5153 }
5154
5155 return true;
5156}
5157
5158bool ValidateGetProgramivRobustANGLE(Context *context,
5159 GLuint program,
5160 GLenum pname,
5161 GLsizei bufSize,
5162 GLsizei *numParams)
5163{
5164 if (!ValidateRobustEntryPoint(context, bufSize))
5165 {
5166 return false;
5167 }
5168
5169 if (!ValidateGetProgramiv(context, program, pname, numParams))
5170 {
5171 return false;
5172 }
5173
5174 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5175 {
5176 return false;
5177 }
5178
5179 return true;
5180}
5181
Geoff Lang740d9022016-10-07 11:20:52 -04005182bool ValidateGetRenderbufferParameteriv(Context *context,
5183 GLenum target,
5184 GLenum pname,
5185 GLint *params)
5186{
5187 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5188}
5189
5190bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5191 GLenum target,
5192 GLenum pname,
5193 GLsizei bufSize,
5194 GLsizei *length,
5195 GLint *params)
5196{
5197 if (!ValidateRobustEntryPoint(context, bufSize))
5198 {
5199 return false;
5200 }
5201
5202 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5203 {
5204 return false;
5205 }
5206
5207 if (!ValidateRobustBufferSize(context, bufSize, *length))
5208 {
5209 return false;
5210 }
5211
5212 return true;
5213}
5214
Geoff Langd7d0ed32016-10-07 11:33:51 -04005215bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5216{
5217 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5218}
5219
5220bool ValidateGetShaderivRobustANGLE(Context *context,
5221 GLuint shader,
5222 GLenum pname,
5223 GLsizei bufSize,
5224 GLsizei *length,
5225 GLint *params)
5226{
5227 if (!ValidateRobustEntryPoint(context, bufSize))
5228 {
5229 return false;
5230 }
5231
5232 if (!ValidateGetShaderivBase(context, shader, pname, length))
5233 {
5234 return false;
5235 }
5236
5237 if (!ValidateRobustBufferSize(context, bufSize, *length))
5238 {
5239 return false;
5240 }
5241
5242 return true;
5243}
5244
Geoff Langc1984ed2016-10-07 12:41:00 -04005245bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5246{
5247 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5248}
5249
5250bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5251 GLenum target,
5252 GLenum pname,
5253 GLsizei bufSize,
5254 GLsizei *length,
5255 GLfloat *params)
5256{
5257 if (!ValidateRobustEntryPoint(context, bufSize))
5258 {
5259 return false;
5260 }
5261
5262 if (!ValidateGetTexParameterBase(context, target, pname, length))
5263 {
5264 return false;
5265 }
5266
5267 if (!ValidateRobustBufferSize(context, bufSize, *length))
5268 {
5269 return false;
5270 }
5271
5272 return true;
5273}
5274
5275bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5276{
5277 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5278}
5279
5280bool ValidateGetTexParameterivRobustANGLE(Context *context,
5281 GLenum target,
5282 GLenum pname,
5283 GLsizei bufSize,
5284 GLsizei *length,
5285 GLint *params)
5286{
5287 if (!ValidateRobustEntryPoint(context, bufSize))
5288 {
5289 return false;
5290 }
5291
5292 if (!ValidateGetTexParameterBase(context, target, pname, length))
5293 {
5294 return false;
5295 }
5296
5297 if (!ValidateRobustBufferSize(context, bufSize, *length))
5298 {
5299 return false;
5300 }
5301
5302 return true;
5303}
5304
5305bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5306{
5307 return ValidateTexParameterBase(context, target, pname, -1, &param);
5308}
5309
5310bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5311{
5312 return ValidateTexParameterBase(context, target, pname, -1, params);
5313}
5314
5315bool ValidateTexParameterfvRobustANGLE(Context *context,
5316 GLenum target,
5317 GLenum pname,
5318 GLsizei bufSize,
5319 const GLfloat *params)
5320{
5321 if (!ValidateRobustEntryPoint(context, bufSize))
5322 {
5323 return false;
5324 }
5325
5326 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5327}
5328
5329bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5330{
5331 return ValidateTexParameterBase(context, target, pname, -1, &param);
5332}
5333
5334bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5335{
5336 return ValidateTexParameterBase(context, target, pname, -1, params);
5337}
5338
5339bool ValidateTexParameterivRobustANGLE(Context *context,
5340 GLenum target,
5341 GLenum pname,
5342 GLsizei bufSize,
5343 const GLint *params)
5344{
5345 if (!ValidateRobustEntryPoint(context, bufSize))
5346 {
5347 return false;
5348 }
5349
5350 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5351}
5352
5353bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5354{
5355 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5356}
5357
5358bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5359 GLuint sampler,
5360 GLenum pname,
5361 GLuint bufSize,
5362 GLsizei *length,
5363 GLfloat *params)
5364{
5365 if (!ValidateRobustEntryPoint(context, bufSize))
5366 {
5367 return false;
5368 }
5369
5370 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5371 {
5372 return false;
5373 }
5374
5375 if (!ValidateRobustBufferSize(context, bufSize, *length))
5376 {
5377 return false;
5378 }
5379
5380 return true;
5381}
5382
5383bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5384{
5385 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5386}
5387
5388bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5389 GLuint sampler,
5390 GLenum pname,
5391 GLuint bufSize,
5392 GLsizei *length,
5393 GLint *params)
5394{
5395 if (!ValidateRobustEntryPoint(context, bufSize))
5396 {
5397 return false;
5398 }
5399
5400 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5401 {
5402 return false;
5403 }
5404
5405 if (!ValidateRobustBufferSize(context, bufSize, *length))
5406 {
5407 return false;
5408 }
5409
5410 return true;
5411}
5412
5413bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5414{
5415 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5416}
5417
5418bool ValidateSamplerParameterfv(Context *context,
5419 GLuint sampler,
5420 GLenum pname,
5421 const GLfloat *params)
5422{
5423 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5424}
5425
5426bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5427 GLuint sampler,
5428 GLenum pname,
5429 GLsizei bufSize,
5430 const GLfloat *params)
5431{
5432 if (!ValidateRobustEntryPoint(context, bufSize))
5433 {
5434 return false;
5435 }
5436
5437 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5438}
5439
5440bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5441{
5442 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5443}
5444
5445bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5446{
5447 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5448}
5449
5450bool ValidateSamplerParameterivRobustANGLE(Context *context,
5451 GLuint sampler,
5452 GLenum pname,
5453 GLsizei bufSize,
5454 const GLint *params)
5455{
5456 if (!ValidateRobustEntryPoint(context, bufSize))
5457 {
5458 return false;
5459 }
5460
5461 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5462}
5463
Geoff Lang0b031062016-10-13 14:30:04 -04005464bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5465{
5466 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5467}
5468
5469bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5470 GLuint index,
5471 GLenum pname,
5472 GLsizei bufSize,
5473 GLsizei *length,
5474 GLfloat *params)
5475{
5476 if (!ValidateRobustEntryPoint(context, bufSize))
5477 {
5478 return false;
5479 }
5480
5481 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5482 {
5483 return false;
5484 }
5485
5486 if (!ValidateRobustBufferSize(context, bufSize, *length))
5487 {
5488 return false;
5489 }
5490
5491 return true;
5492}
5493
5494bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5495{
5496 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5497}
5498
5499bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5500 GLuint index,
5501 GLenum pname,
5502 GLsizei bufSize,
5503 GLsizei *length,
5504 GLint *params)
5505{
5506 if (!ValidateRobustEntryPoint(context, bufSize))
5507 {
5508 return false;
5509 }
5510
5511 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5512 {
5513 return false;
5514 }
5515
5516 if (!ValidateRobustBufferSize(context, bufSize, *length))
5517 {
5518 return false;
5519 }
5520
5521 return true;
5522}
5523
5524bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5525{
5526 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5527}
5528
5529bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5530 GLuint index,
5531 GLenum pname,
5532 GLsizei bufSize,
5533 GLsizei *length,
5534 void **pointer)
5535{
5536 if (!ValidateRobustEntryPoint(context, bufSize))
5537 {
5538 return false;
5539 }
5540
5541 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5542 {
5543 return false;
5544 }
5545
5546 if (!ValidateRobustBufferSize(context, bufSize, *length))
5547 {
5548 return false;
5549 }
5550
5551 return true;
5552}
5553
5554bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5555{
5556 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5557}
5558
5559bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5560 GLuint index,
5561 GLenum pname,
5562 GLsizei bufSize,
5563 GLsizei *length,
5564 GLint *params)
5565{
5566 if (!ValidateRobustEntryPoint(context, bufSize))
5567 {
5568 return false;
5569 }
5570
5571 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5572 {
5573 return false;
5574 }
5575
5576 if (!ValidateRobustBufferSize(context, bufSize, *length))
5577 {
5578 return false;
5579 }
5580
5581 return true;
5582}
5583
5584bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5585{
5586 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5587}
5588
5589bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5590 GLuint index,
5591 GLenum pname,
5592 GLsizei bufSize,
5593 GLsizei *length,
5594 GLuint *params)
5595{
5596 if (!ValidateRobustEntryPoint(context, bufSize))
5597 {
5598 return false;
5599 }
5600
5601 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5602 {
5603 return false;
5604 }
5605
5606 if (!ValidateRobustBufferSize(context, bufSize, *length))
5607 {
5608 return false;
5609 }
5610
5611 return true;
5612}
5613
Geoff Lang6899b872016-10-14 11:30:13 -04005614bool ValidateGetActiveUniformBlockiv(Context *context,
5615 GLuint program,
5616 GLuint uniformBlockIndex,
5617 GLenum pname,
5618 GLint *params)
5619{
5620 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5621}
5622
5623bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5624 GLuint program,
5625 GLuint uniformBlockIndex,
5626 GLenum pname,
5627 GLsizei bufSize,
5628 GLsizei *length,
5629 GLint *params)
5630{
5631 if (!ValidateRobustEntryPoint(context, bufSize))
5632 {
5633 return false;
5634 }
5635
5636 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5637 {
5638 return false;
5639 }
5640
5641 if (!ValidateRobustBufferSize(context, bufSize, *length))
5642 {
5643 return false;
5644 }
5645
5646 return true;
5647}
5648
Geoff Lang0a9661f2016-10-20 10:59:20 -07005649bool ValidateGetInternalFormativ(Context *context,
5650 GLenum target,
5651 GLenum internalformat,
5652 GLenum pname,
5653 GLsizei bufSize,
5654 GLint *params)
5655{
5656 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5657 nullptr);
5658}
5659
5660bool ValidateGetInternalFormativRobustANGLE(Context *context,
5661 GLenum target,
5662 GLenum internalformat,
5663 GLenum pname,
5664 GLsizei bufSize,
5665 GLsizei *length,
5666 GLint *params)
5667{
5668 if (!ValidateRobustEntryPoint(context, bufSize))
5669 {
5670 return false;
5671 }
5672
5673 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5674 {
5675 return false;
5676 }
5677
5678 if (!ValidateRobustBufferSize(context, bufSize, *length))
5679 {
5680 return false;
5681 }
5682
5683 return true;
5684}
5685
Jamie Madillc29968b2016-01-20 11:17:23 -05005686} // namespace gl