blob: e12f5c2306fdaefb5021de4f87cb27181d943377 [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
He Yunchaoced53ae2016-11-29 15:00:51 +08001930bool ValidateRenderbufferStorageParametersBase(gl::Context *context,
1931 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 ValidateRenderbufferStorageParametersANGLE(gl::Context *context,
1986 GLenum target,
1987 GLsizei samples,
1988 GLenum internalformat,
1989 GLsizei width,
1990 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -08001991{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001992 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001993
1994 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001995 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001996 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001997 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001998 {
Jamie Madill437fa652016-05-03 15:13:24 -04001999 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08002000 return false;
2001 }
2002
2003 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
2004 // the specified storage. This is different than ES 3.0 in which a sample number higher
2005 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08002006 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03002007 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08002008 {
Geoff Langa4903b72015-03-02 16:02:48 -08002009 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2010 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2011 {
Jamie Madill437fa652016-05-03 15:13:24 -04002012 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08002013 return false;
2014 }
Corentin Walleze0902642014-11-04 12:32:15 -08002015 }
2016
He Yunchaoced53ae2016-11-29 15:00:51 +08002017 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
2018 width, height);
Corentin Walleze0902642014-11-04 12:32:15 -08002019}
2020
He Yunchaoced53ae2016-11-29 15:00:51 +08002021bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
2022 GLenum target,
2023 GLenum attachment,
2024 GLenum renderbuffertarget,
2025 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002026{
Shannon Woods1da3cf62014-06-27 15:32:23 -04002027 if (!ValidFramebufferTarget(target))
2028 {
Jamie Madill437fa652016-05-03 15:13:24 -04002029 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002030 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04002031 }
2032
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002033 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002034
Jamie Madill84115c92015-04-23 15:00:07 -04002035 ASSERT(framebuffer);
2036 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002037 {
Jamie Madill437fa652016-05-03 15:13:24 -04002038 context->handleError(
2039 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002040 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002041 }
2042
Jamie Madillb4472272014-07-03 10:38:55 -04002043 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002044 {
Jamie Madillb4472272014-07-03 10:38:55 -04002045 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002046 }
2047
Jamie Madillab9d82c2014-01-21 16:38:14 -05002048 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2049 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2050 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2051 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2052 if (renderbuffer != 0)
2053 {
2054 if (!context->getRenderbuffer(renderbuffer))
2055 {
Jamie Madill437fa652016-05-03 15:13:24 -04002056 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002057 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05002058 }
2059 }
2060
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002061 return true;
2062}
2063
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002064bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002065 GLint srcX0,
2066 GLint srcY0,
2067 GLint srcX1,
2068 GLint srcY1,
2069 GLint dstX0,
2070 GLint dstY0,
2071 GLint dstX1,
2072 GLint dstY1,
2073 GLbitfield mask,
2074 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002075{
2076 switch (filter)
2077 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002078 case GL_NEAREST:
2079 break;
2080 case GL_LINEAR:
2081 break;
2082 default:
2083 context->handleError(Error(GL_INVALID_ENUM));
2084 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002085 }
2086
2087 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
2088 {
Jamie Madill437fa652016-05-03 15:13:24 -04002089 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002090 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002091 }
2092
2093 if (mask == 0)
2094 {
2095 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
2096 // buffers are copied.
2097 return false;
2098 }
2099
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002100 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
2101 // color buffer, leaving only nearest being unfiltered from above
2102 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
2103 {
Jamie Madill437fa652016-05-03 15:13:24 -04002104 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002105 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002106 }
2107
Jamie Madill51f40ec2016-06-15 14:06:00 -04002108 const auto &glState = context->getGLState();
2109 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2110 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05002111
2112 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002113 {
Jamie Madill437fa652016-05-03 15:13:24 -04002114 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002115 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002116 }
2117
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002118 if (readFramebuffer->id() == drawFramebuffer->id())
2119 {
2120 context->handleError(Error(GL_INVALID_OPERATION));
2121 return false;
2122 }
2123
Jamie Madill51f40ec2016-06-15 14:06:00 -04002124 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002125 {
Jamie Madill437fa652016-05-03 15:13:24 -04002126 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002127 return false;
2128 }
2129
Jamie Madill51f40ec2016-06-15 14:06:00 -04002130 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002131 {
Jamie Madill437fa652016-05-03 15:13:24 -04002132 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002133 return false;
2134 }
2135
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002136 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002137 {
Jamie Madill437fa652016-05-03 15:13:24 -04002138 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002139 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002140 }
2141
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002142 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2143
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002144 if (mask & GL_COLOR_BUFFER_BIT)
2145 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002146 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002147 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002148
He Yunchao66a41a22016-12-15 16:45:05 +08002149 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002150 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002151 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002152
Geoff Langa15472a2015-08-11 11:48:03 -04002153 for (size_t drawbufferIdx = 0;
2154 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002155 {
Geoff Langa15472a2015-08-11 11:48:03 -04002156 const FramebufferAttachment *attachment =
2157 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2158 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002159 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002160 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002161
Geoff Langb2f3d052013-08-13 12:49:27 -04002162 // The GL ES 3.0.2 spec (pg 193) states that:
2163 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002164 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2165 // as well
2166 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2167 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002168 // Changes with EXT_color_buffer_float:
2169 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002170 GLenum readComponentType = readFormat.info->componentType;
2171 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002172 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002173 readComponentType == GL_SIGNED_NORMALIZED);
2174 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2175 drawComponentType == GL_SIGNED_NORMALIZED);
2176
2177 if (extensions.colorBufferFloat)
2178 {
2179 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2180 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2181
2182 if (readFixedOrFloat != drawFixedOrFloat)
2183 {
Jamie Madill437fa652016-05-03 15:13:24 -04002184 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002185 "If the read buffer contains fixed-point or "
2186 "floating-point values, the draw buffer "
2187 "must as well."));
2188 return false;
2189 }
2190 }
2191 else if (readFixedPoint != drawFixedPoint)
2192 {
Jamie Madill437fa652016-05-03 15:13:24 -04002193 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002194 "If the read buffer contains fixed-point "
2195 "values, the draw buffer must as well."));
2196 return false;
2197 }
2198
2199 if (readComponentType == GL_UNSIGNED_INT &&
2200 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002201 {
Jamie Madill437fa652016-05-03 15:13:24 -04002202 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002203 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002204 }
2205
Jamie Madill6163c752015-12-07 16:32:59 -05002206 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002207 {
Jamie Madill437fa652016-05-03 15:13:24 -04002208 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002209 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002210 }
2211
Jamie Madilla3944d42016-07-22 22:13:26 -04002212 if (readColorBuffer->getSamples() > 0 &&
2213 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002214 {
Jamie Madill437fa652016-05-03 15:13:24 -04002215 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002216 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002217 }
2218 }
2219 }
2220
Jamie Madilla3944d42016-07-22 22:13:26 -04002221 if ((readFormat.info->componentType == GL_INT ||
2222 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2223 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002224 {
Jamie Madill437fa652016-05-03 15:13:24 -04002225 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002226 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002227 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002228 }
He Yunchao66a41a22016-12-15 16:45:05 +08002229 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2230 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2231 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2232 // situation is an application error that would lead to a crash in ANGLE.
2233 else if (drawFramebuffer->hasEnabledDrawBuffer())
2234 {
2235 context->handleError(Error(
2236 GL_INVALID_OPERATION,
2237 "Attempt to read from a missing color attachment of a complete framebuffer."));
2238 return false;
2239 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002240 }
2241
He Yunchaoced53ae2016-11-29 15:00:51 +08002242 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002243 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2244 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002245 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002246 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002247 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002248 const gl::FramebufferAttachment *readBuffer =
2249 readFramebuffer->getAttachment(attachments[i]);
2250 const gl::FramebufferAttachment *drawBuffer =
2251 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002252
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002253 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002254 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002255 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002256 {
Jamie Madill437fa652016-05-03 15:13:24 -04002257 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002258 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002259 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002260
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002261 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002262 {
Jamie Madill437fa652016-05-03 15:13:24 -04002263 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002264 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002265 }
2266 }
He Yunchao66a41a22016-12-15 16:45:05 +08002267 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2268 else if (drawBuffer)
2269 {
2270 context->handleError(Error(GL_INVALID_OPERATION,
2271 "Attempt to read from a missing depth/stencil "
2272 "attachment of a complete framebuffer."));
2273 return false;
2274 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002275 }
2276 }
2277
2278 return true;
2279}
2280
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002281bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002282 GLint x,
2283 GLint y,
2284 GLsizei width,
2285 GLsizei height,
2286 GLenum format,
2287 GLenum type,
2288 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002289{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002290 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2291}
2292
2293bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2294 GLint x,
2295 GLint y,
2296 GLsizei width,
2297 GLsizei height,
2298 GLenum format,
2299 GLenum type,
2300 GLsizei bufSize,
2301 GLsizei *length,
2302 GLvoid *pixels)
2303{
2304 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002305 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002306 return false;
2307 }
2308
Geoff Lang62fce5b2016-09-30 10:46:35 -04002309 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2310 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002311 {
Geoff Langb1196682014-07-23 13:47:29 -04002312 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002313 }
2314
Geoff Lang62fce5b2016-09-30 10:46:35 -04002315 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002316 {
Geoff Langb1196682014-07-23 13:47:29 -04002317 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002318 }
2319
Jamie Madillc29968b2016-01-20 11:17:23 -05002320 return true;
2321}
2322
2323bool ValidateReadnPixelsEXT(Context *context,
2324 GLint x,
2325 GLint y,
2326 GLsizei width,
2327 GLsizei height,
2328 GLenum format,
2329 GLenum type,
2330 GLsizei bufSize,
2331 GLvoid *pixels)
2332{
2333 if (bufSize < 0)
2334 {
Jamie Madill437fa652016-05-03 15:13:24 -04002335 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002336 return false;
2337 }
2338
Geoff Lang62fce5b2016-09-30 10:46:35 -04002339 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2340 pixels);
2341}
Jamie Madill26e91952014-03-05 15:01:27 -05002342
Geoff Lang62fce5b2016-09-30 10:46:35 -04002343bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2344 GLint x,
2345 GLint y,
2346 GLsizei width,
2347 GLsizei height,
2348 GLenum format,
2349 GLenum type,
2350 GLsizei bufSize,
2351 GLsizei *length,
2352 GLvoid *data)
2353{
2354 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002355 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002356 return false;
2357 }
2358
Geoff Lang62fce5b2016-09-30 10:46:35 -04002359 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002360 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002361 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002362 }
2363
Geoff Lang62fce5b2016-09-30 10:46:35 -04002364 if (!ValidateRobustBufferSize(context, bufSize, *length))
2365 {
2366 return false;
2367 }
2368
2369 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002370}
2371
Olli Etuaho41997e72016-03-10 13:38:39 +02002372bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002373{
2374 if (!context->getExtensions().occlusionQueryBoolean &&
2375 !context->getExtensions().disjointTimerQuery)
2376 {
Jamie Madill437fa652016-05-03 15:13:24 -04002377 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002378 return false;
2379 }
2380
Olli Etuaho41997e72016-03-10 13:38:39 +02002381 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002382}
2383
Olli Etuaho41997e72016-03-10 13:38:39 +02002384bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002385{
2386 if (!context->getExtensions().occlusionQueryBoolean &&
2387 !context->getExtensions().disjointTimerQuery)
2388 {
Jamie Madill437fa652016-05-03 15:13:24 -04002389 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002390 return false;
2391 }
2392
Olli Etuaho41997e72016-03-10 13:38:39 +02002393 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002394}
2395
2396bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002397{
2398 if (!ValidQueryType(context, target))
2399 {
Jamie Madill437fa652016-05-03 15:13:24 -04002400 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002401 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002402 }
2403
2404 if (id == 0)
2405 {
Jamie Madill437fa652016-05-03 15:13:24 -04002406 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002407 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002408 }
2409
2410 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2411 // of zero, if the active query object name for <target> is non-zero (for the
2412 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2413 // the active query for either target is non-zero), if <id> is the name of an
2414 // existing query object whose type does not match <target>, or if <id> is the
2415 // active query object name for any query type, the error INVALID_OPERATION is
2416 // generated.
2417
2418 // Ensure no other queries are active
2419 // NOTE: If other queries than occlusion are supported, we will need to check
2420 // separately that:
2421 // a) The query ID passed is not the current active query for any target/type
2422 // b) There are no active queries for the requested target (and in the case
2423 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2424 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002425
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002426 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002427 {
Jamie Madill437fa652016-05-03 15:13:24 -04002428 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002429 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002430 }
2431
2432 Query *queryObject = context->getQuery(id, true, target);
2433
2434 // check that name was obtained with glGenQueries
2435 if (!queryObject)
2436 {
Jamie Madill437fa652016-05-03 15:13:24 -04002437 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002438 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002439 }
2440
2441 // check for type mismatch
2442 if (queryObject->getType() != target)
2443 {
Jamie Madill437fa652016-05-03 15:13:24 -04002444 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002445 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002446 }
2447
2448 return true;
2449}
2450
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002451bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2452{
2453 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002454 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002455 {
Jamie Madill437fa652016-05-03 15:13:24 -04002456 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002457 return false;
2458 }
2459
2460 return ValidateBeginQueryBase(context, target, id);
2461}
2462
2463bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002464{
2465 if (!ValidQueryType(context, target))
2466 {
Jamie Madill437fa652016-05-03 15:13:24 -04002467 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002468 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002469 }
2470
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002471 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002472
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002473 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002474 {
Jamie Madill437fa652016-05-03 15:13:24 -04002475 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002476 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002477 }
2478
Jamie Madill45c785d2014-05-13 14:09:34 -04002479 return true;
2480}
2481
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002482bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2483{
2484 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002485 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002486 {
Jamie Madill437fa652016-05-03 15:13:24 -04002487 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002488 return false;
2489 }
2490
2491 return ValidateEndQueryBase(context, target);
2492}
2493
2494bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2495{
2496 if (!context->getExtensions().disjointTimerQuery)
2497 {
Jamie Madill437fa652016-05-03 15:13:24 -04002498 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002499 return false;
2500 }
2501
2502 if (target != GL_TIMESTAMP_EXT)
2503 {
Jamie Madill437fa652016-05-03 15:13:24 -04002504 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002505 return false;
2506 }
2507
2508 Query *queryObject = context->getQuery(id, true, target);
2509 if (queryObject == nullptr)
2510 {
Jamie Madill437fa652016-05-03 15:13:24 -04002511 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002512 return false;
2513 }
2514
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002515 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002516 {
Jamie Madill437fa652016-05-03 15:13:24 -04002517 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002518 return false;
2519 }
2520
2521 return true;
2522}
2523
Geoff Lang2186c382016-10-14 10:54:54 -04002524bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002525{
Geoff Lang2186c382016-10-14 10:54:54 -04002526 if (numParams)
2527 {
2528 *numParams = 0;
2529 }
2530
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002531 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2532 {
Jamie Madill437fa652016-05-03 15:13:24 -04002533 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002534 return false;
2535 }
2536
2537 switch (pname)
2538 {
2539 case GL_CURRENT_QUERY_EXT:
2540 if (target == GL_TIMESTAMP_EXT)
2541 {
Jamie Madill437fa652016-05-03 15:13:24 -04002542 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002543 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2544 return false;
2545 }
2546 break;
2547 case GL_QUERY_COUNTER_BITS_EXT:
2548 if (!context->getExtensions().disjointTimerQuery ||
2549 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2550 {
Jamie Madill437fa652016-05-03 15:13:24 -04002551 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002552 return false;
2553 }
2554 break;
2555 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002556 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002557 return false;
2558 }
2559
Geoff Lang2186c382016-10-14 10:54:54 -04002560 if (numParams)
2561 {
2562 // All queries return only one value
2563 *numParams = 1;
2564 }
2565
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002566 return true;
2567}
2568
2569bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2570{
2571 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002572 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002573 {
Jamie Madill437fa652016-05-03 15:13:24 -04002574 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002575 return false;
2576 }
2577
Geoff Lang2186c382016-10-14 10:54:54 -04002578 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002579}
2580
Geoff Lang2186c382016-10-14 10:54:54 -04002581bool ValidateGetQueryivRobustANGLE(Context *context,
2582 GLenum target,
2583 GLenum pname,
2584 GLsizei bufSize,
2585 GLsizei *length,
2586 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002587{
Geoff Lang2186c382016-10-14 10:54:54 -04002588 if (!ValidateRobustEntryPoint(context, bufSize))
2589 {
2590 return false;
2591 }
2592
2593 if (!ValidateGetQueryivBase(context, target, pname, length))
2594 {
2595 return false;
2596 }
2597
2598 if (!ValidateRobustBufferSize(context, bufSize, *length))
2599 {
2600 return false;
2601 }
2602
2603 return true;
2604}
2605
2606bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2607{
2608 if (numParams)
2609 {
2610 *numParams = 0;
2611 }
2612
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002613 Query *queryObject = context->getQuery(id, false, GL_NONE);
2614
2615 if (!queryObject)
2616 {
Jamie Madill437fa652016-05-03 15:13:24 -04002617 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002618 return false;
2619 }
2620
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002621 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002622 {
Jamie Madill437fa652016-05-03 15:13:24 -04002623 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002624 return false;
2625 }
2626
2627 switch (pname)
2628 {
2629 case GL_QUERY_RESULT_EXT:
2630 case GL_QUERY_RESULT_AVAILABLE_EXT:
2631 break;
2632
2633 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002634 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002635 return false;
2636 }
2637
Geoff Lang2186c382016-10-14 10:54:54 -04002638 if (numParams)
2639 {
2640 *numParams = 1;
2641 }
2642
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002643 return true;
2644}
2645
2646bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2647{
2648 if (!context->getExtensions().disjointTimerQuery)
2649 {
Jamie Madill437fa652016-05-03 15:13:24 -04002650 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002651 return false;
2652 }
Geoff Lang2186c382016-10-14 10:54:54 -04002653 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2654}
2655
2656bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2657 GLuint id,
2658 GLenum pname,
2659 GLsizei bufSize,
2660 GLsizei *length,
2661 GLint *params)
2662{
2663 if (!context->getExtensions().disjointTimerQuery)
2664 {
2665 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2666 return false;
2667 }
2668
2669 if (!ValidateRobustEntryPoint(context, bufSize))
2670 {
2671 return false;
2672 }
2673
2674 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2675 {
2676 return false;
2677 }
2678
2679 if (!ValidateRobustBufferSize(context, bufSize, *length))
2680 {
2681 return false;
2682 }
2683
2684 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002685}
2686
2687bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2688{
2689 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002690 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002691 {
Jamie Madill437fa652016-05-03 15:13:24 -04002692 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002693 return false;
2694 }
Geoff Lang2186c382016-10-14 10:54:54 -04002695 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2696}
2697
2698bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2699 GLuint id,
2700 GLenum pname,
2701 GLsizei bufSize,
2702 GLsizei *length,
2703 GLuint *params)
2704{
2705 if (!context->getExtensions().disjointTimerQuery &&
2706 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2707 {
2708 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2709 return false;
2710 }
2711
2712 if (!ValidateRobustEntryPoint(context, bufSize))
2713 {
2714 return false;
2715 }
2716
2717 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2718 {
2719 return false;
2720 }
2721
2722 if (!ValidateRobustBufferSize(context, bufSize, *length))
2723 {
2724 return false;
2725 }
2726
2727 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002728}
2729
2730bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2731{
2732 if (!context->getExtensions().disjointTimerQuery)
2733 {
Jamie Madill437fa652016-05-03 15:13:24 -04002734 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002735 return false;
2736 }
Geoff Lang2186c382016-10-14 10:54:54 -04002737 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2738}
2739
2740bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2741 GLuint id,
2742 GLenum pname,
2743 GLsizei bufSize,
2744 GLsizei *length,
2745 GLint64 *params)
2746{
2747 if (!context->getExtensions().disjointTimerQuery)
2748 {
2749 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2750 return false;
2751 }
2752
2753 if (!ValidateRobustEntryPoint(context, bufSize))
2754 {
2755 return false;
2756 }
2757
2758 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2759 {
2760 return false;
2761 }
2762
2763 if (!ValidateRobustBufferSize(context, bufSize, *length))
2764 {
2765 return false;
2766 }
2767
2768 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002769}
2770
2771bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2772{
2773 if (!context->getExtensions().disjointTimerQuery)
2774 {
Jamie Madill437fa652016-05-03 15:13:24 -04002775 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002776 return false;
2777 }
Geoff Lang2186c382016-10-14 10:54:54 -04002778 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2779}
2780
2781bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2782 GLuint id,
2783 GLenum pname,
2784 GLsizei bufSize,
2785 GLsizei *length,
2786 GLuint64 *params)
2787{
2788 if (!context->getExtensions().disjointTimerQuery)
2789 {
2790 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2791 return false;
2792 }
2793
2794 if (!ValidateRobustEntryPoint(context, bufSize))
2795 {
2796 return false;
2797 }
2798
2799 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2800 {
2801 return false;
2802 }
2803
2804 if (!ValidateRobustBufferSize(context, bufSize, *length))
2805 {
2806 return false;
2807 }
2808
2809 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002810}
2811
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002812bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002813 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002814 GLuint program,
2815 GLint location,
2816 GLsizei count)
2817{
2818 // Check for ES31 program uniform entry points
2819 if (context->getClientVersion() < Version(3, 1))
2820 {
2821 context->handleError(Error(GL_INVALID_OPERATION));
2822 return false;
2823 }
2824
2825 const LinkedUniform *uniform = nullptr;
2826 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002827 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2828 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002829}
2830
Frank Henigmana98a6472017-02-02 21:38:32 -05002831bool ValidateProgramUniform1iv(gl::Context *context,
2832 GLuint program,
2833 GLint location,
2834 GLsizei count,
2835 const GLint *value)
2836{
2837 // Check for ES31 program uniform entry points
2838 if (context->getClientVersion() < Version(3, 1))
2839 {
2840 context->handleError(Error(GL_INVALID_OPERATION));
2841 return false;
2842 }
2843
2844 const LinkedUniform *uniform = nullptr;
2845 gl::Program *programObject = GetValidProgram(context, program);
2846 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2847 ValidateUniform1ivValue(context, uniform->type, count, value);
2848}
2849
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002850bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002851 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002852 GLuint program,
2853 GLint location,
2854 GLsizei count,
2855 GLboolean transpose)
2856{
2857 // Check for ES31 program uniform entry points
2858 if (context->getClientVersion() < Version(3, 1))
2859 {
2860 context->handleError(Error(GL_INVALID_OPERATION));
2861 return false;
2862 }
2863
2864 const LinkedUniform *uniform = nullptr;
2865 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002866 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2867 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002868}
2869
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002870bool ValidateUniform(gl::Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002871{
2872 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002873 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002874 {
Jamie Madill437fa652016-05-03 15:13:24 -04002875 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002876 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002877 }
2878
Jamie Madill62d31cb2015-09-11 13:25:51 -04002879 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002880 gl::Program *programObject = context->getGLState().getProgram();
2881 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2882 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002883}
2884
Frank Henigmana98a6472017-02-02 21:38:32 -05002885bool ValidateUniform1iv(gl::Context *context, GLint location, GLsizei count, const GLint *value)
2886{
2887 const LinkedUniform *uniform = nullptr;
2888 gl::Program *programObject = context->getGLState().getProgram();
2889 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2890 ValidateUniform1ivValue(context, uniform->type, count, value);
2891}
2892
He Yunchaoced53ae2016-11-29 15:00:51 +08002893bool ValidateUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002894 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002895 GLint location,
2896 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002897 GLboolean transpose)
2898{
2899 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002900 int rows = VariableRowCount(valueType);
2901 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002902 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002903 {
Jamie Madill437fa652016-05-03 15:13:24 -04002904 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002905 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002906 }
2907
Martin Radev1be913c2016-07-11 17:59:16 +03002908 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002909 {
Jamie Madill437fa652016-05-03 15:13:24 -04002910 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002911 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002912 }
2913
Jamie Madill62d31cb2015-09-11 13:25:51 -04002914 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002915 gl::Program *programObject = context->getGLState().getProgram();
2916 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2917 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002918}
2919
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002920bool ValidateStateQuery(ValidationContext *context,
2921 GLenum pname,
2922 GLenum *nativeType,
2923 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002924{
2925 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2926 {
Jamie Madill437fa652016-05-03 15:13:24 -04002927 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002928 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002929 }
2930
Jamie Madill0af26e12015-03-05 19:54:33 -05002931 const Caps &caps = context->getCaps();
2932
Jamie Madill893ab082014-05-16 16:56:10 -04002933 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2934 {
2935 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2936
Jamie Madill0af26e12015-03-05 19:54:33 -05002937 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002938 {
Jamie Madill437fa652016-05-03 15:13:24 -04002939 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002940 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002941 }
2942 }
2943
2944 switch (pname)
2945 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002946 case GL_TEXTURE_BINDING_2D:
2947 case GL_TEXTURE_BINDING_CUBE_MAP:
2948 case GL_TEXTURE_BINDING_3D:
2949 case GL_TEXTURE_BINDING_2D_ARRAY:
2950 break;
2951 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2952 if (!context->getExtensions().eglStreamConsumerExternal &&
2953 !context->getExtensions().eglImageExternal)
2954 {
2955 context->handleError(Error(GL_INVALID_ENUM,
2956 "Neither NV_EGL_stream_consumer_external nor "
2957 "GL_OES_EGL_image_external extensions enabled"));
2958 return false;
2959 }
2960 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002961
He Yunchaoced53ae2016-11-29 15:00:51 +08002962 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2963 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002964 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002965 if (context->getGLState().getReadFramebuffer()->checkStatus(
2966 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002967 {
Jamie Madill437fa652016-05-03 15:13:24 -04002968 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002969 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002970 }
2971
Jamie Madill51f40ec2016-06-15 14:06:00 -04002972 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2973 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002974
2975 if (framebuffer->getReadBufferState() == GL_NONE)
2976 {
2977 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2978 return false;
2979 }
2980
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002981 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002982 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002983 {
Jamie Madill437fa652016-05-03 15:13:24 -04002984 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002985 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002986 }
2987 }
2988 break;
2989
He Yunchaoced53ae2016-11-29 15:00:51 +08002990 default:
2991 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002992 }
2993
2994 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002995 if (*numParams == 0)
2996 {
2997 return false;
2998 }
2999
3000 return true;
3001}
3002
3003bool ValidateRobustStateQuery(ValidationContext *context,
3004 GLenum pname,
3005 GLsizei bufSize,
3006 GLenum *nativeType,
3007 unsigned int *numParams)
3008{
3009 if (!ValidateRobustEntryPoint(context, bufSize))
3010 {
3011 return false;
3012 }
3013
3014 if (!ValidateStateQuery(context, pname, nativeType, numParams))
3015 {
3016 return false;
3017 }
3018
3019 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04003020 {
3021 return false;
3022 }
3023
3024 return true;
3025}
3026
Jamie Madillc29968b2016-01-20 11:17:23 -05003027bool ValidateCopyTexImageParametersBase(ValidationContext *context,
3028 GLenum target,
3029 GLint level,
3030 GLenum internalformat,
3031 bool isSubImage,
3032 GLint xoffset,
3033 GLint yoffset,
3034 GLint zoffset,
3035 GLint x,
3036 GLint y,
3037 GLsizei width,
3038 GLsizei height,
3039 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04003040 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04003041{
Jamie Madill560a8d82014-05-21 13:06:20 -04003042 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
3043 {
Jamie Madill437fa652016-05-03 15:13:24 -04003044 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003045 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003046 }
3047
He Yunchaoced53ae2016-11-29 15:00:51 +08003048 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3049 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04003050 {
Jamie Madill437fa652016-05-03 15:13:24 -04003051 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003052 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003053 }
3054
3055 if (border != 0)
3056 {
Jamie Madill437fa652016-05-03 15:13:24 -04003057 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003058 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003059 }
3060
3061 if (!ValidMipLevel(context, target, level))
3062 {
Jamie Madill437fa652016-05-03 15:13:24 -04003063 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003064 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003065 }
3066
Jamie Madill51f40ec2016-06-15 14:06:00 -04003067 const auto &state = context->getGLState();
3068 auto readFramebuffer = state.getReadFramebuffer();
3069 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003070 {
Jamie Madill437fa652016-05-03 15:13:24 -04003071 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003072 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003073 }
3074
Jamie Madill51f40ec2016-06-15 14:06:00 -04003075 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003076 {
Jamie Madill437fa652016-05-03 15:13:24 -04003077 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003078 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003079 }
3080
Martin Radev138064f2016-07-15 12:03:41 +03003081 if (readFramebuffer->getReadBufferState() == GL_NONE)
3082 {
3083 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3084 return false;
3085 }
3086
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003087 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3088 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003089 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003090 // situation is an application error that would lead to a crash in ANGLE.
3091 if (readFramebuffer->getReadColorbuffer() == nullptr)
3092 {
3093 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3094 return false;
3095 }
3096
Geoff Langaae65a42014-05-26 12:43:44 -04003097 const gl::Caps &caps = context->getCaps();
3098
Geoff Langaae65a42014-05-26 12:43:44 -04003099 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003100 switch (target)
3101 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003102 case GL_TEXTURE_2D:
3103 maxDimension = caps.max2DTextureSize;
3104 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003105
He Yunchaoced53ae2016-11-29 15:00:51 +08003106 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3107 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3108 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3109 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3110 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3111 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3112 maxDimension = caps.maxCubeMapTextureSize;
3113 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003114
He Yunchaoced53ae2016-11-29 15:00:51 +08003115 case GL_TEXTURE_2D_ARRAY:
3116 maxDimension = caps.max2DTextureSize;
3117 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003118
He Yunchaoced53ae2016-11-29 15:00:51 +08003119 case GL_TEXTURE_3D:
3120 maxDimension = caps.max3DTextureSize;
3121 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003122
He Yunchaoced53ae2016-11-29 15:00:51 +08003123 default:
3124 context->handleError(Error(GL_INVALID_ENUM));
3125 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003126 }
3127
Jamie Madillc29968b2016-01-20 11:17:23 -05003128 gl::Texture *texture =
3129 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003130 if (!texture)
3131 {
Jamie Madill437fa652016-05-03 15:13:24 -04003132 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003133 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003134 }
3135
Geoff Lang69cce582015-09-17 13:20:36 -04003136 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003137 {
Jamie Madill437fa652016-05-03 15:13:24 -04003138 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003139 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003140 }
3141
Geoff Lang5d601382014-07-22 15:14:06 -04003142 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3143
3144 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003145 {
Jamie Madill437fa652016-05-03 15:13:24 -04003146 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003147 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003148 }
3149
Geoff Lang44ff5a72017-02-03 15:15:43 -05003150 if (formatInfo.compressed &&
3151 !ValidCompressedImageSize(context, internalformat, xoffset, yoffset, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003152 {
Jamie Madill437fa652016-05-03 15:13:24 -04003153 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003154 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003155 }
3156
3157 if (isSubImage)
3158 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003159 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3160 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3161 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003162 {
Jamie Madill437fa652016-05-03 15:13:24 -04003163 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003164 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003165 }
3166 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003167 else
3168 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003169 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003170 {
Jamie Madill437fa652016-05-03 15:13:24 -04003171 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003172 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003173 }
3174
Geoff Langeb66a6e2016-10-31 13:06:12 -04003175 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003176 {
Jamie Madill437fa652016-05-03 15:13:24 -04003177 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003178 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003179 }
3180
3181 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003182 if (static_cast<int>(width) > maxLevelDimension ||
3183 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003184 {
Jamie Madill437fa652016-05-03 15:13:24 -04003185 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003186 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003187 }
3188 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003189
Jamie Madill0c8abca2016-07-22 20:21:26 -04003190 if (textureFormatOut)
3191 {
3192 *textureFormatOut = texture->getFormat(target, level);
3193 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003194
3195 // Detect texture copying feedback loops for WebGL.
3196 if (context->getExtensions().webglCompatibility)
3197 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05003198 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05003199 {
3200 context->handleError(Error(GL_INVALID_OPERATION,
3201 "Texture copying feedback loop formed between Framebuffer "
3202 "and specified Texture level."));
3203 return false;
3204 }
3205 }
3206
Jamie Madill560a8d82014-05-21 13:06:20 -04003207 return true;
3208}
3209
Jiajia Qind9671222016-11-29 16:30:31 +08003210bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003211{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003212 switch (mode)
3213 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003214 case GL_POINTS:
3215 case GL_LINES:
3216 case GL_LINE_LOOP:
3217 case GL_LINE_STRIP:
3218 case GL_TRIANGLES:
3219 case GL_TRIANGLE_STRIP:
3220 case GL_TRIANGLE_FAN:
3221 break;
3222 default:
3223 context->handleError(Error(GL_INVALID_ENUM));
3224 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003225 }
3226
Jamie Madill250d33f2014-06-06 17:09:03 -04003227 if (count < 0)
3228 {
Jamie Madill437fa652016-05-03 15:13:24 -04003229 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003230 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003231 }
3232
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003233 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003234
Jamie Madill250d33f2014-06-06 17:09:03 -04003235 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003236 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003237 {
Jamie Madill437fa652016-05-03 15:13:24 -04003238 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003239 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003240 }
3241
Jamie Madillcbcde722017-01-06 14:50:00 -05003242 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3243 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003244 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003245 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3246 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003247 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003248 const FramebufferAttachment *dsAttachment =
3249 framebuffer->getStencilOrDepthStencilAttachment();
3250 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003251 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003252 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003253
3254 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3255 bool differentWritemasks =
3256 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3257 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3258 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3259 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3260
3261 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003262 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003263 if (!context->getExtensions().webglCompatibility)
3264 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003265 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3266 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003267 }
Jamie Madill437fa652016-05-03 15:13:24 -04003268 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003269 return false;
3270 }
Jamie Madillac528012014-06-20 13:21:23 -04003271 }
3272
Jamie Madill51f40ec2016-06-15 14:06:00 -04003273 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003274 {
Jamie Madill437fa652016-05-03 15:13:24 -04003275 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003276 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003277 }
3278
Geoff Lang7dd2e102014-11-10 15:19:26 -05003279 gl::Program *program = state.getProgram();
3280 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003281 {
Jamie Madill437fa652016-05-03 15:13:24 -04003282 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003283 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003284 }
3285
Geoff Lang7dd2e102014-11-10 15:19:26 -05003286 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003287 {
Jamie Madill437fa652016-05-03 15:13:24 -04003288 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003289 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003290 }
3291
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003292 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003293 for (unsigned int uniformBlockIndex = 0;
3294 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003295 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003296 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003297 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003298 const OffsetBindingPointer<Buffer> &uniformBuffer =
3299 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003300
Geoff Lang5d124a62015-09-15 13:03:27 -04003301 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003302 {
3303 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003304 context->handleError(
3305 Error(GL_INVALID_OPERATION,
3306 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003307 return false;
3308 }
3309
Geoff Lang5d124a62015-09-15 13:03:27 -04003310 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003311 if (uniformBufferSize == 0)
3312 {
3313 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003314 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003315 }
3316
Jamie Madill62d31cb2015-09-11 13:25:51 -04003317 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003318 {
3319 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003320 context->handleError(
3321 Error(GL_INVALID_OPERATION,
3322 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003323 return false;
3324 }
3325 }
3326
Jamie Madilla4595b82017-01-11 17:36:34 -05003327 // Detect rendering feedback loops for WebGL.
3328 if (context->getExtensions().webglCompatibility)
3329 {
3330 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3331 {
3332 context->handleError(
3333 Error(GL_INVALID_OPERATION,
3334 "Rendering feedback loop formed between Framebuffer and active Texture."));
3335 return false;
3336 }
3337 }
3338
Jamie Madill250d33f2014-06-06 17:09:03 -04003339 // No-op if zero count
3340 return (count > 0);
3341}
3342
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003343bool ValidateDrawArrays(ValidationContext *context,
3344 GLenum mode,
3345 GLint first,
3346 GLsizei count,
3347 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003348{
Jamie Madillfd716582014-06-06 17:09:04 -04003349 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003350 {
Jamie Madill437fa652016-05-03 15:13:24 -04003351 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003352 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003353 }
3354
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003355 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003356 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003357 if (curTransformFeedback && curTransformFeedback->isActive() &&
3358 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003359 {
3360 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003361 // that does not match the current transform feedback object's draw mode (if transform
3362 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003363 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003364 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003365 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003366 }
3367
Jiajia Qind9671222016-11-29 16:30:31 +08003368 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003369 {
3370 return false;
3371 }
3372
Corentin Wallez71168a02016-12-19 15:11:18 -08003373 // Check the computation of maxVertex doesn't overflow.
3374 // - first < 0 or count < 0 have been checked as an error condition
3375 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3376 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3377 ASSERT(count > 0 && first >= 0);
3378 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3379 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003380 {
3381 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3382 return false;
3383 }
3384
Corentin Wallez71168a02016-12-19 15:11:18 -08003385 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003386 {
3387 return false;
3388 }
3389
3390 return true;
3391}
3392
He Yunchaoced53ae2016-11-29 15:00:51 +08003393bool ValidateDrawArraysInstanced(Context *context,
3394 GLenum mode,
3395 GLint first,
3396 GLsizei count,
3397 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003398{
3399 if (primcount < 0)
3400 {
Jamie Madill437fa652016-05-03 15:13:24 -04003401 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003402 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003403 }
3404
Jamie Madill2b976812014-08-25 15:47:49 -04003405 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003406 {
3407 return false;
3408 }
3409
3410 // No-op if zero primitive count
3411 return (primcount > 0);
3412}
3413
Geoff Lang87a93302014-09-16 13:29:43 -04003414static bool ValidateDrawInstancedANGLE(Context *context)
3415{
3416 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003417 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003418
Geoff Lang7dd2e102014-11-10 15:19:26 -05003419 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003420
3421 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003422 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003423 {
3424 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003425 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003426 {
3427 return true;
3428 }
3429 }
3430
Jamie Madill437fa652016-05-03 15:13:24 -04003431 context->handleError(Error(GL_INVALID_OPERATION,
3432 "ANGLE_instanced_arrays requires that at least one active attribute"
3433 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003434 return false;
3435}
3436
He Yunchaoced53ae2016-11-29 15:00:51 +08003437bool ValidateDrawArraysInstancedANGLE(Context *context,
3438 GLenum mode,
3439 GLint first,
3440 GLsizei count,
3441 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003442{
3443 if (!ValidateDrawInstancedANGLE(context))
3444 {
3445 return false;
3446 }
3447
3448 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3449}
3450
Jiajia Qind9671222016-11-29 16:30:31 +08003451bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003452{
Jamie Madill250d33f2014-06-06 17:09:03 -04003453 switch (type)
3454 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003455 case GL_UNSIGNED_BYTE:
3456 case GL_UNSIGNED_SHORT:
3457 break;
3458 case GL_UNSIGNED_INT:
3459 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3460 {
3461 context->handleError(Error(GL_INVALID_ENUM));
3462 return false;
3463 }
3464 break;
3465 default:
3466 context->handleError(Error(GL_INVALID_ENUM));
3467 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003468 }
3469
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003470 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003471
3472 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003473 if (curTransformFeedback && curTransformFeedback->isActive() &&
3474 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003475 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003476 // It is an invalid operation to call DrawElements, DrawRangeElements or
3477 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003478 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003479 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003480 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003481 }
3482
Jiajia Qind9671222016-11-29 16:30:31 +08003483 return true;
3484}
3485
3486bool ValidateDrawElements(ValidationContext *context,
3487 GLenum mode,
3488 GLsizei count,
3489 GLenum type,
3490 const GLvoid *indices,
3491 GLsizei primcount,
3492 IndexRange *indexRangeOut)
3493{
3494 if (!ValidateDrawElementsBase(context, type))
3495 return false;
3496
3497 const State &state = context->getGLState();
3498
Jamie Madill250d33f2014-06-06 17:09:03 -04003499 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003500 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003501 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003502 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04003503 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003504 }
3505
He Yunchaoced53ae2016-11-29 15:00:51 +08003506 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003507 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003508
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003509 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3510
3511 if (context->getExtensions().webglCompatibility)
3512 {
3513 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3514 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3515 {
3516 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3517 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3518 // data type passed to the call, or an INVALID_OPERATION error is generated.
3519 context->handleError(Error(GL_INVALID_OPERATION,
3520 "indices must be a multiple of the element type size."));
3521 return false;
3522 }
3523 if (!elementArrayBuffer && count > 0)
3524 {
3525 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3526 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3527 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3528 context->handleError(Error(GL_INVALID_OPERATION,
3529 "There is no element array buffer bound and count > 0."));
3530 return false;
3531 }
3532 }
3533
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003534 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003535 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003536 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003537 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003538 GLint64 offset = reinterpret_cast<GLint64>(indices);
3539 GLint64 byteCount =
3540 static_cast<GLint64>(typeBytes) * static_cast<GLint64>(count) + offset;
3541
3542 // check for integer overflows
3543 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeBytes) ||
3544 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3545 {
3546 context->handleError(Error(GL_OUT_OF_MEMORY, "Integer overflow."));
3547 return false;
3548 }
3549
3550 // Check for reading past the end of the bound buffer object
3551 if (byteCount > elementArrayBuffer->getSize())
3552 {
3553 context->handleError(
3554 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
3555 return false;
3556 }
3557 }
3558 else if (!indices)
3559 {
3560 // This is an application error that would normally result in a crash,
3561 // but we catch it and return an error
3562 context->handleError(
3563 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003564 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003565 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003566 }
3567
Jiajia Qind9671222016-11-29 16:30:31 +08003568 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003569 {
3570 return false;
3571 }
3572
Jamie Madill2b976812014-08-25 15:47:49 -04003573 // Use max index to validate if our vertex buffers are large enough for the pull.
3574 // TODO: offer fast path, with disabled index validation.
3575 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3576 if (elementArrayBuffer)
3577 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003578 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003579 Error error =
3580 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3581 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003582 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003583 {
Jamie Madill437fa652016-05-03 15:13:24 -04003584 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003585 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003586 }
3587 }
3588 else
3589 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003590 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003591 }
3592
Jamie Madille79b1e12015-11-04 16:36:37 -05003593 // If we use an index greater than our maximum supported index range, return an error.
3594 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3595 // return an error if possible here.
3596 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3597 {
Jamie Madill437fa652016-05-03 15:13:24 -04003598 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003599 return false;
3600 }
3601
Corentin Wallez92db6942016-12-09 13:10:36 -05003602 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3603 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003604 {
3605 return false;
3606 }
3607
Geoff Lang3edfe032015-09-04 16:38:24 -04003608 // No op if there are no real indices in the index data (all are primitive restart).
3609 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003610}
3611
Geoff Langb1196682014-07-23 13:47:29 -04003612bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003613 GLenum mode,
3614 GLsizei count,
3615 GLenum type,
3616 const GLvoid *indices,
3617 GLsizei primcount,
3618 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003619{
3620 if (primcount < 0)
3621 {
Jamie Madill437fa652016-05-03 15:13:24 -04003622 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003623 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003624 }
3625
Jamie Madill2b976812014-08-25 15:47:49 -04003626 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003627 {
3628 return false;
3629 }
3630
3631 // No-op zero primitive count
3632 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003633}
3634
Geoff Lang3edfe032015-09-04 16:38:24 -04003635bool ValidateDrawElementsInstancedANGLE(Context *context,
3636 GLenum mode,
3637 GLsizei count,
3638 GLenum type,
3639 const GLvoid *indices,
3640 GLsizei primcount,
3641 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003642{
3643 if (!ValidateDrawInstancedANGLE(context))
3644 {
3645 return false;
3646 }
3647
He Yunchaoced53ae2016-11-29 15:00:51 +08003648 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3649 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003650}
3651
He Yunchaoced53ae2016-11-29 15:00:51 +08003652bool ValidateFramebufferTextureBase(Context *context,
3653 GLenum target,
3654 GLenum attachment,
3655 GLuint texture,
3656 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003657{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003658 if (!ValidFramebufferTarget(target))
3659 {
Jamie Madill437fa652016-05-03 15:13:24 -04003660 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003661 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003662 }
3663
3664 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003665 {
3666 return false;
3667 }
3668
Jamie Madill55ec3b12014-07-03 10:38:57 -04003669 if (texture != 0)
3670 {
3671 gl::Texture *tex = context->getTexture(texture);
3672
3673 if (tex == NULL)
3674 {
Jamie Madill437fa652016-05-03 15:13:24 -04003675 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003676 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003677 }
3678
3679 if (level < 0)
3680 {
Jamie Madill437fa652016-05-03 15:13:24 -04003681 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003682 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003683 }
3684 }
3685
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003686 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003687 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003688
Jamie Madill84115c92015-04-23 15:00:07 -04003689 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003690 {
Jamie Madill437fa652016-05-03 15:13:24 -04003691 context->handleError(
3692 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003693 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003694 }
3695
3696 return true;
3697}
3698
He Yunchaoced53ae2016-11-29 15:00:51 +08003699bool ValidateFramebufferTexture2D(Context *context,
3700 GLenum target,
3701 GLenum attachment,
3702 GLenum textarget,
3703 GLuint texture,
3704 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003705{
He Yunchaoced53ae2016-11-29 15:00:51 +08003706 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3707 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003708 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3709 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003710 {
Jamie Madill437fa652016-05-03 15:13:24 -04003711 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003712 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003713 }
3714
3715 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003716 {
3717 return false;
3718 }
3719
Jamie Madill55ec3b12014-07-03 10:38:57 -04003720 if (texture != 0)
3721 {
3722 gl::Texture *tex = context->getTexture(texture);
3723 ASSERT(tex);
3724
Jamie Madill2a6564e2014-07-11 09:53:19 -04003725 const gl::Caps &caps = context->getCaps();
3726
Jamie Madill55ec3b12014-07-03 10:38:57 -04003727 switch (textarget)
3728 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003729 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003730 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003731 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003732 {
Jamie Madill437fa652016-05-03 15:13:24 -04003733 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003734 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003735 }
3736 if (tex->getTarget() != GL_TEXTURE_2D)
3737 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003738 context->handleError(Error(GL_INVALID_OPERATION,
3739 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003740 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003741 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003742 }
3743 break;
3744
He Yunchaoced53ae2016-11-29 15:00:51 +08003745 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3746 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3747 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3748 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3749 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3750 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003751 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003752 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003753 {
Jamie Madill437fa652016-05-03 15:13:24 -04003754 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003755 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003756 }
3757 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3758 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003759 context->handleError(Error(GL_INVALID_OPERATION,
3760 "Textarget must match the texture target type."));
3761 return false;
3762 }
3763 }
3764 break;
3765
3766 case GL_TEXTURE_2D_MULTISAMPLE:
3767 {
3768 if (context->getClientVersion() < ES_3_1)
3769 {
3770 context->handleError(Error(GL_INVALID_OPERATION,
3771 "Texture target requires at least OpenGL ES 3.1."));
3772 return false;
3773 }
3774
3775 if (level != 0)
3776 {
3777 context->handleError(
3778 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
3779 return false;
3780 }
3781 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
3782 {
3783 context->handleError(Error(GL_INVALID_OPERATION,
3784 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003785 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003786 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003787 }
3788 break;
3789
He Yunchaoced53ae2016-11-29 15:00:51 +08003790 default:
3791 context->handleError(Error(GL_INVALID_ENUM));
3792 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003793 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003794
Jamie Madilla3944d42016-07-22 22:13:26 -04003795 const Format &format = tex->getFormat(textarget, level);
3796 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003797 {
Jamie Madill437fa652016-05-03 15:13:24 -04003798 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003799 return false;
3800 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003801 }
3802
Jamie Madill570f7c82014-07-03 10:38:54 -04003803 return true;
3804}
3805
Geoff Langb1196682014-07-23 13:47:29 -04003806bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003807{
3808 if (program == 0)
3809 {
Jamie Madill437fa652016-05-03 15:13:24 -04003810 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003811 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003812 }
3813
Dian Xiang769769a2015-09-09 15:20:08 -07003814 gl::Program *programObject = GetValidProgram(context, program);
3815 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003816 {
3817 return false;
3818 }
3819
Jamie Madill0063c512014-08-25 15:47:53 -04003820 if (!programObject || !programObject->isLinked())
3821 {
Jamie Madill437fa652016-05-03 15:13:24 -04003822 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003823 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003824 }
3825
Geoff Lang7dd2e102014-11-10 15:19:26 -05003826 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003827 {
Jamie Madill437fa652016-05-03 15:13:24 -04003828 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003829 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003830 }
3831
Jamie Madill0063c512014-08-25 15:47:53 -04003832 return true;
3833}
3834
He Yunchaoced53ae2016-11-29 15:00:51 +08003835bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003836{
3837 return ValidateGetUniformBase(context, program, location);
3838}
3839
He Yunchaoced53ae2016-11-29 15:00:51 +08003840bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003841{
Jamie Madill78f41802014-08-25 15:47:55 -04003842 return ValidateGetUniformBase(context, program, location);
3843}
3844
Geoff Langf41d0ee2016-10-07 13:04:23 -04003845static bool ValidateSizedGetUniform(Context *context,
3846 GLuint program,
3847 GLint location,
3848 GLsizei bufSize,
3849 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003850{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003851 if (length)
3852 {
3853 *length = 0;
3854 }
3855
Jamie Madill78f41802014-08-25 15:47:55 -04003856 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003857 {
Jamie Madill78f41802014-08-25 15:47:55 -04003858 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003859 }
3860
Geoff Langf41d0ee2016-10-07 13:04:23 -04003861 if (bufSize < 0)
3862 {
3863 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3864 return false;
3865 }
3866
Jamie Madilla502c742014-08-28 17:19:13 -04003867 gl::Program *programObject = context->getProgram(program);
3868 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003869
Jamie Madill78f41802014-08-25 15:47:55 -04003870 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003871 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003872 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003873 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003874 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003875 context->handleError(
3876 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003877 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003878 }
3879
Geoff Langf41d0ee2016-10-07 13:04:23 -04003880 if (length)
3881 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003882 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003883 }
3884
Jamie Madill0063c512014-08-25 15:47:53 -04003885 return true;
3886}
3887
He Yunchaoced53ae2016-11-29 15:00:51 +08003888bool ValidateGetnUniformfvEXT(Context *context,
3889 GLuint program,
3890 GLint location,
3891 GLsizei bufSize,
3892 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003893{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003894 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003895}
3896
He Yunchaoced53ae2016-11-29 15:00:51 +08003897bool ValidateGetnUniformivEXT(Context *context,
3898 GLuint program,
3899 GLint location,
3900 GLsizei bufSize,
3901 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003902{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003903 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3904}
3905
3906bool ValidateGetUniformfvRobustANGLE(Context *context,
3907 GLuint program,
3908 GLint location,
3909 GLsizei bufSize,
3910 GLsizei *length,
3911 GLfloat *params)
3912{
3913 if (!ValidateRobustEntryPoint(context, bufSize))
3914 {
3915 return false;
3916 }
3917
3918 // bufSize is validated in ValidateSizedGetUniform
3919 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3920}
3921
3922bool ValidateGetUniformivRobustANGLE(Context *context,
3923 GLuint program,
3924 GLint location,
3925 GLsizei bufSize,
3926 GLsizei *length,
3927 GLint *params)
3928{
3929 if (!ValidateRobustEntryPoint(context, bufSize))
3930 {
3931 return false;
3932 }
3933
3934 // bufSize is validated in ValidateSizedGetUniform
3935 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3936}
3937
3938bool ValidateGetUniformuivRobustANGLE(Context *context,
3939 GLuint program,
3940 GLint location,
3941 GLsizei bufSize,
3942 GLsizei *length,
3943 GLuint *params)
3944{
3945 if (!ValidateRobustEntryPoint(context, bufSize))
3946 {
3947 return false;
3948 }
3949
3950 if (context->getClientMajorVersion() < 3)
3951 {
3952 context->handleError(
3953 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3954 return false;
3955 }
3956
3957 // bufSize is validated in ValidateSizedGetUniform
3958 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003959}
3960
He Yunchaoced53ae2016-11-29 15:00:51 +08003961bool ValidateDiscardFramebufferBase(Context *context,
3962 GLenum target,
3963 GLsizei numAttachments,
3964 const GLenum *attachments,
3965 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003966{
3967 if (numAttachments < 0)
3968 {
Jamie Madill437fa652016-05-03 15:13:24 -04003969 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003970 return false;
3971 }
3972
3973 for (GLsizei i = 0; i < numAttachments; ++i)
3974 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003975 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003976 {
3977 if (defaultFramebuffer)
3978 {
Jamie Madill437fa652016-05-03 15:13:24 -04003979 context->handleError(Error(
3980 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003981 return false;
3982 }
3983
3984 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3985 {
Jamie Madill437fa652016-05-03 15:13:24 -04003986 context->handleError(Error(GL_INVALID_OPERATION,
3987 "Requested color attachment is greater than the maximum "
3988 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003989 return false;
3990 }
3991 }
3992 else
3993 {
3994 switch (attachments[i])
3995 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003996 case GL_DEPTH_ATTACHMENT:
3997 case GL_STENCIL_ATTACHMENT:
3998 case GL_DEPTH_STENCIL_ATTACHMENT:
3999 if (defaultFramebuffer)
4000 {
4001 context->handleError(
4002 Error(GL_INVALID_ENUM,
4003 "Invalid attachment when the default framebuffer is bound"));
4004 return false;
4005 }
4006 break;
4007 case GL_COLOR:
4008 case GL_DEPTH:
4009 case GL_STENCIL:
4010 if (!defaultFramebuffer)
4011 {
4012 context->handleError(
4013 Error(GL_INVALID_ENUM,
4014 "Invalid attachment when the default framebuffer is not bound"));
4015 return false;
4016 }
4017 break;
4018 default:
4019 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07004020 return false;
Austin Kinross08332632015-05-05 13:35:47 -07004021 }
4022 }
4023 }
4024
4025 return true;
4026}
4027
Austin Kinross6ee1e782015-05-29 17:05:37 -07004028bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
4029{
4030 // Note that debug marker calls must not set error state
4031
4032 if (length < 0)
4033 {
4034 return false;
4035 }
4036
4037 if (marker == nullptr)
4038 {
4039 return false;
4040 }
4041
4042 return true;
4043}
4044
4045bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
4046{
4047 // Note that debug marker calls must not set error state
4048
4049 if (length < 0)
4050 {
4051 return false;
4052 }
4053
4054 if (length > 0 && marker == nullptr)
4055 {
4056 return false;
4057 }
4058
4059 return true;
4060}
4061
Geoff Langdcab33b2015-07-21 13:03:16 -04004062bool ValidateEGLImageTargetTexture2DOES(Context *context,
4063 egl::Display *display,
4064 GLenum target,
4065 egl::Image *image)
4066{
Geoff Langa8406172015-07-21 16:53:39 -04004067 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4068 {
Jamie Madill437fa652016-05-03 15:13:24 -04004069 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004070 return false;
4071 }
4072
4073 switch (target)
4074 {
4075 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004076 if (!context->getExtensions().eglImage)
4077 {
4078 context->handleError(Error(
4079 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4080 }
4081 break;
4082
4083 case GL_TEXTURE_EXTERNAL_OES:
4084 if (!context->getExtensions().eglImageExternal)
4085 {
4086 context->handleError(Error(
4087 GL_INVALID_ENUM,
4088 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4089 }
Geoff Langa8406172015-07-21 16:53:39 -04004090 break;
4091
4092 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004093 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004094 return false;
4095 }
4096
4097 if (!display->isValidImage(image))
4098 {
Jamie Madill437fa652016-05-03 15:13:24 -04004099 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004100 return false;
4101 }
4102
4103 if (image->getSamples() > 0)
4104 {
Jamie Madill437fa652016-05-03 15:13:24 -04004105 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004106 "cannot create a 2D texture from a multisampled EGL image."));
4107 return false;
4108 }
4109
Jamie Madilla3944d42016-07-22 22:13:26 -04004110 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004111 if (!textureCaps.texturable)
4112 {
Jamie Madill437fa652016-05-03 15:13:24 -04004113 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004114 "EGL image internal format is not supported as a texture."));
4115 return false;
4116 }
4117
Geoff Langdcab33b2015-07-21 13:03:16 -04004118 return true;
4119}
4120
4121bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4122 egl::Display *display,
4123 GLenum target,
4124 egl::Image *image)
4125{
Geoff Langa8406172015-07-21 16:53:39 -04004126 if (!context->getExtensions().eglImage)
4127 {
Jamie Madill437fa652016-05-03 15:13:24 -04004128 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004129 return false;
4130 }
4131
4132 switch (target)
4133 {
4134 case GL_RENDERBUFFER:
4135 break;
4136
4137 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004138 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004139 return false;
4140 }
4141
4142 if (!display->isValidImage(image))
4143 {
Jamie Madill437fa652016-05-03 15:13:24 -04004144 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004145 return false;
4146 }
4147
Jamie Madilla3944d42016-07-22 22:13:26 -04004148 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004149 if (!textureCaps.renderable)
4150 {
Jamie Madill437fa652016-05-03 15:13:24 -04004151 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004152 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4153 return false;
4154 }
4155
Geoff Langdcab33b2015-07-21 13:03:16 -04004156 return true;
4157}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004158
4159bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4160{
Geoff Lang36167ab2015-12-07 10:27:14 -05004161 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004162 {
4163 // The default VAO should always exist
4164 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004165 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004166 return false;
4167 }
4168
4169 return true;
4170}
4171
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004172bool ValidateLinkProgram(Context *context, GLuint program)
4173{
4174 if (context->hasActiveTransformFeedback(program))
4175 {
4176 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004177 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004178 "Cannot link program while program is associated with an active "
4179 "transform feedback object."));
4180 return false;
4181 }
4182 return true;
4183}
4184
Geoff Langc5629752015-12-07 16:29:04 -05004185bool ValidateProgramBinaryBase(Context *context,
4186 GLuint program,
4187 GLenum binaryFormat,
4188 const void *binary,
4189 GLint length)
4190{
4191 Program *programObject = GetValidProgram(context, program);
4192 if (programObject == nullptr)
4193 {
4194 return false;
4195 }
4196
4197 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4198 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4199 programBinaryFormats.end())
4200 {
Jamie Madill437fa652016-05-03 15:13:24 -04004201 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004202 return false;
4203 }
4204
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004205 if (context->hasActiveTransformFeedback(program))
4206 {
4207 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004208 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004209 "Cannot change program binary while program is associated with "
4210 "an active transform feedback object."));
4211 return false;
4212 }
4213
Geoff Langc5629752015-12-07 16:29:04 -05004214 return true;
4215}
4216
4217bool ValidateGetProgramBinaryBase(Context *context,
4218 GLuint program,
4219 GLsizei bufSize,
4220 GLsizei *length,
4221 GLenum *binaryFormat,
4222 void *binary)
4223{
4224 Program *programObject = GetValidProgram(context, program);
4225 if (programObject == nullptr)
4226 {
4227 return false;
4228 }
4229
4230 if (!programObject->isLinked())
4231 {
Jamie Madill437fa652016-05-03 15:13:24 -04004232 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004233 return false;
4234 }
4235
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004236 if (context->getCaps().programBinaryFormats.empty())
4237 {
4238 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4239 return false;
4240 }
4241
Geoff Langc5629752015-12-07 16:29:04 -05004242 return true;
4243}
Jamie Madillc29968b2016-01-20 11:17:23 -05004244
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004245bool ValidateUseProgram(Context *context, GLuint program)
4246{
4247 if (program != 0)
4248 {
4249 Program *programObject = context->getProgram(program);
4250 if (!programObject)
4251 {
4252 // ES 3.1.0 section 7.3 page 72
4253 if (context->getShader(program))
4254 {
Jamie Madill437fa652016-05-03 15:13:24 -04004255 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004256 Error(GL_INVALID_OPERATION,
4257 "Attempted to use a single shader instead of a shader program."));
4258 return false;
4259 }
4260 else
4261 {
Jamie Madill437fa652016-05-03 15:13:24 -04004262 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004263 return false;
4264 }
4265 }
4266 if (!programObject->isLinked())
4267 {
Jamie Madill437fa652016-05-03 15:13:24 -04004268 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004269 return false;
4270 }
4271 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004272 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004273 {
4274 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004275 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004276 Error(GL_INVALID_OPERATION,
4277 "Cannot change active program while transform feedback is unpaused."));
4278 return false;
4279 }
4280
4281 return true;
4282}
4283
Jamie Madillc29968b2016-01-20 11:17:23 -05004284bool ValidateCopyTexImage2D(ValidationContext *context,
4285 GLenum target,
4286 GLint level,
4287 GLenum internalformat,
4288 GLint x,
4289 GLint y,
4290 GLsizei width,
4291 GLsizei height,
4292 GLint border)
4293{
Martin Radev1be913c2016-07-11 17:59:16 +03004294 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004295 {
4296 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4297 0, x, y, width, height, border);
4298 }
4299
Martin Radev1be913c2016-07-11 17:59:16 +03004300 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004301 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4302 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004303}
Jamie Madillc29968b2016-01-20 11:17:23 -05004304
4305bool ValidateFramebufferRenderbuffer(Context *context,
4306 GLenum target,
4307 GLenum attachment,
4308 GLenum renderbuffertarget,
4309 GLuint renderbuffer)
4310{
4311 if (!ValidFramebufferTarget(target) ||
4312 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4313 {
Jamie Madill437fa652016-05-03 15:13:24 -04004314 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004315 return false;
4316 }
4317
4318 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4319 renderbuffertarget, renderbuffer);
4320}
4321
4322bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4323{
4324 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4325 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4326 {
Jamie Madill437fa652016-05-03 15:13:24 -04004327 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004328 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4329 return false;
4330 }
4331
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004332 ASSERT(context->getGLState().getDrawFramebuffer());
4333 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004334 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4335
4336 // This should come first before the check for the default frame buffer
4337 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4338 // rather than INVALID_OPERATION
4339 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4340 {
4341 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4342
4343 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004344 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4345 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004346 {
4347 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004348 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4349 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4350 // 3.1 is still a bit ambiguous about the error, but future specs are
4351 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004352 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004353 return false;
4354 }
4355 else if (bufs[colorAttachment] >= maxColorAttachment)
4356 {
Jamie Madill437fa652016-05-03 15:13:24 -04004357 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004358 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004359 return false;
4360 }
4361 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4362 frameBufferId != 0)
4363 {
4364 // INVALID_OPERATION-GL is bound to buffer and ith argument
4365 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004366 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004367 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4368 return false;
4369 }
4370 }
4371
4372 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4373 // and n is not 1 or bufs is bound to value other than BACK and NONE
4374 if (frameBufferId == 0)
4375 {
4376 if (n != 1)
4377 {
Jamie Madill437fa652016-05-03 15:13:24 -04004378 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004379 "n must be 1 when GL is bound to the default framebuffer"));
4380 return false;
4381 }
4382
4383 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4384 {
Jamie Madill437fa652016-05-03 15:13:24 -04004385 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004386 GL_INVALID_OPERATION,
4387 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4388 return false;
4389 }
4390 }
4391
4392 return true;
4393}
4394
4395bool ValidateCopyTexSubImage2D(Context *context,
4396 GLenum target,
4397 GLint level,
4398 GLint xoffset,
4399 GLint yoffset,
4400 GLint x,
4401 GLint y,
4402 GLsizei width,
4403 GLsizei height)
4404{
Martin Radev1be913c2016-07-11 17:59:16 +03004405 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004406 {
4407 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4408 yoffset, x, y, width, height, 0);
4409 }
4410
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004411 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4412 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004413}
4414
Geoff Lang496c02d2016-10-20 11:38:11 -07004415bool ValidateGetBufferPointervBase(Context *context,
4416 GLenum target,
4417 GLenum pname,
4418 GLsizei *length,
4419 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004420{
Geoff Lang496c02d2016-10-20 11:38:11 -07004421 if (length)
4422 {
4423 *length = 0;
4424 }
4425
4426 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4427 {
4428 context->handleError(
4429 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004430 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004431 return false;
4432 }
4433
Olli Etuaho4f667482016-03-30 15:56:35 +03004434 if (!ValidBufferTarget(context, target))
4435 {
Jamie Madill437fa652016-05-03 15:13:24 -04004436 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004437 return false;
4438 }
4439
Geoff Lang496c02d2016-10-20 11:38:11 -07004440 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004441 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004442 case GL_BUFFER_MAP_POINTER:
4443 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004444
Geoff Lang496c02d2016-10-20 11:38:11 -07004445 default:
4446 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4447 return false;
4448 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004449
4450 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4451 // target bound to zero generate an INVALID_OPERATION error."
4452 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004453 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004454 {
Jamie Madill437fa652016-05-03 15:13:24 -04004455 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004456 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4457 return false;
4458 }
4459
Geoff Lang496c02d2016-10-20 11:38:11 -07004460 if (length)
4461 {
4462 *length = 1;
4463 }
4464
Olli Etuaho4f667482016-03-30 15:56:35 +03004465 return true;
4466}
4467
4468bool ValidateUnmapBufferBase(Context *context, GLenum target)
4469{
4470 if (!ValidBufferTarget(context, target))
4471 {
Jamie Madill437fa652016-05-03 15:13:24 -04004472 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004473 return false;
4474 }
4475
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004476 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004477
4478 if (buffer == nullptr || !buffer->isMapped())
4479 {
Jamie Madill437fa652016-05-03 15:13:24 -04004480 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004481 return false;
4482 }
4483
4484 return true;
4485}
4486
4487bool ValidateMapBufferRangeBase(Context *context,
4488 GLenum target,
4489 GLintptr offset,
4490 GLsizeiptr length,
4491 GLbitfield access)
4492{
4493 if (!ValidBufferTarget(context, target))
4494 {
Jamie Madill437fa652016-05-03 15:13:24 -04004495 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004496 return false;
4497 }
4498
4499 if (offset < 0 || length < 0)
4500 {
Jamie Madill437fa652016-05-03 15:13:24 -04004501 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004502 return false;
4503 }
4504
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004505 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004506
4507 if (!buffer)
4508 {
Jamie Madill437fa652016-05-03 15:13:24 -04004509 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004510 return false;
4511 }
4512
4513 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004514 CheckedNumeric<size_t> checkedOffset(offset);
4515 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004516
Jamie Madille2e406c2016-06-02 13:04:10 -04004517 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004518 {
Jamie Madill437fa652016-05-03 15:13:24 -04004519 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004520 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4521 return false;
4522 }
4523
4524 // Check for invalid bits in the mask
4525 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4526 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4527 GL_MAP_UNSYNCHRONIZED_BIT;
4528
4529 if (access & ~(allAccessBits))
4530 {
Jamie Madill437fa652016-05-03 15:13:24 -04004531 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004532 return false;
4533 }
4534
4535 if (length == 0)
4536 {
Jamie Madill437fa652016-05-03 15:13:24 -04004537 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004538 return false;
4539 }
4540
4541 if (buffer->isMapped())
4542 {
Jamie Madill437fa652016-05-03 15:13:24 -04004543 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004544 return false;
4545 }
4546
4547 // Check for invalid bit combinations
4548 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4549 {
Jamie Madill437fa652016-05-03 15:13:24 -04004550 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004551 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4552 return false;
4553 }
4554
4555 GLbitfield writeOnlyBits =
4556 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4557
4558 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4559 {
Jamie Madill437fa652016-05-03 15:13:24 -04004560 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004561 "Invalid access bits when mapping buffer for reading: 0x%X.",
4562 access));
4563 return false;
4564 }
4565
4566 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4567 {
Jamie Madill437fa652016-05-03 15:13:24 -04004568 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004569 GL_INVALID_OPERATION,
4570 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4571 return false;
4572 }
4573 return true;
4574}
4575
4576bool ValidateFlushMappedBufferRangeBase(Context *context,
4577 GLenum target,
4578 GLintptr offset,
4579 GLsizeiptr length)
4580{
4581 if (offset < 0 || length < 0)
4582 {
Jamie Madill437fa652016-05-03 15:13:24 -04004583 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004584 return false;
4585 }
4586
4587 if (!ValidBufferTarget(context, target))
4588 {
Jamie Madill437fa652016-05-03 15:13:24 -04004589 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004590 return false;
4591 }
4592
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004593 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004594
4595 if (buffer == nullptr)
4596 {
Jamie Madill437fa652016-05-03 15:13:24 -04004597 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004598 return false;
4599 }
4600
4601 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4602 {
Jamie Madill437fa652016-05-03 15:13:24 -04004603 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004604 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4605 return false;
4606 }
4607
4608 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004609 CheckedNumeric<size_t> checkedOffset(offset);
4610 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004611
Jamie Madille2e406c2016-06-02 13:04:10 -04004612 if (!checkedSize.IsValid() ||
4613 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004614 {
Jamie Madill437fa652016-05-03 15:13:24 -04004615 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004616 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4617 return false;
4618 }
4619
4620 return true;
4621}
4622
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004623bool ValidateGenerateMipmap(Context *context, GLenum target)
4624{
4625 if (!ValidTextureTarget(context, target))
4626 {
4627 context->handleError(Error(GL_INVALID_ENUM));
4628 return false;
4629 }
4630
4631 Texture *texture = context->getTargetTexture(target);
4632
4633 if (texture == nullptr)
4634 {
4635 context->handleError(Error(GL_INVALID_OPERATION));
4636 return false;
4637 }
4638
4639 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4640
4641 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4642 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4643 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4644 {
4645 context->handleError(Error(GL_INVALID_OPERATION));
4646 return false;
4647 }
4648
Jamie Madilla3944d42016-07-22 22:13:26 -04004649 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4650 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4651 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004652
4653 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4654 // unsized formats or that are color renderable and filterable. Since we do not track if
4655 // the texture was created with sized or unsized format (only sized formats are stored),
4656 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4657 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4658 // textures since they're the only texture format that can be created with unsized formats
4659 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4660 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004661 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4662 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004663 {
4664 context->handleError(Error(GL_INVALID_OPERATION));
4665 return false;
4666 }
4667
4668 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004669 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004670 {
4671 context->handleError(Error(GL_INVALID_OPERATION));
4672 return false;
4673 }
4674
4675 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004676 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004677 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4678 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4679 {
Geoff Lang55482a12016-11-21 16:54:01 -05004680 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004681 context->handleError(Error(GL_INVALID_OPERATION));
4682 return false;
4683 }
4684
4685 // Cube completeness check
4686 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4687 {
4688 context->handleError(Error(GL_INVALID_OPERATION));
4689 return false;
4690 }
4691
4692 return true;
4693}
4694
Olli Etuaho41997e72016-03-10 13:38:39 +02004695bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4696{
4697 return ValidateGenOrDelete(context, n);
4698}
4699
4700bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4701{
4702 return ValidateGenOrDelete(context, n);
4703}
4704
4705bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4706{
4707 return ValidateGenOrDelete(context, n);
4708}
4709
4710bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4711{
4712 return ValidateGenOrDelete(context, n);
4713}
4714
4715bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4716{
4717 return ValidateGenOrDelete(context, n);
4718}
4719
4720bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4721{
4722 return ValidateGenOrDelete(context, n);
4723}
4724
4725bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4726{
4727 return ValidateGenOrDelete(context, n);
4728}
4729
4730bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4731{
4732 return ValidateGenOrDelete(context, n);
4733}
4734
4735bool ValidateGenOrDelete(Context *context, GLint n)
4736{
4737 if (n < 0)
4738 {
Jamie Madill437fa652016-05-03 15:13:24 -04004739 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004740 return false;
4741 }
4742 return true;
4743}
4744
Geoff Langf41a7152016-09-19 15:11:17 -04004745bool ValidateEnable(Context *context, GLenum cap)
4746{
4747 if (!ValidCap(context, cap, false))
4748 {
4749 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4750 return false;
4751 }
4752
4753 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4754 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4755 {
4756 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4757 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4758
4759 // We also output an error message to the debugger window if tracing is active, so that
4760 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05004761 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04004762 return false;
4763 }
4764
4765 return true;
4766}
4767
4768bool ValidateDisable(Context *context, GLenum cap)
4769{
4770 if (!ValidCap(context, cap, false))
4771 {
4772 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4773 return false;
4774 }
4775
4776 return true;
4777}
4778
4779bool ValidateIsEnabled(Context *context, GLenum cap)
4780{
4781 if (!ValidCap(context, cap, true))
4782 {
4783 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4784 return false;
4785 }
4786
4787 return true;
4788}
4789
Geoff Langff5b2d52016-09-07 11:32:23 -04004790bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4791{
4792 if (!context->getExtensions().robustClientMemory)
4793 {
4794 context->handleError(
4795 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4796 return false;
4797 }
4798
4799 if (bufSize < 0)
4800 {
4801 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4802 return false;
4803 }
4804
4805 return true;
4806}
4807
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004808bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4809{
4810 if (bufSize < numParams)
4811 {
4812 context->handleError(Error(GL_INVALID_OPERATION,
4813 "%u parameters are required but %i were provided.", numParams,
4814 bufSize));
4815 return false;
4816 }
4817
4818 return true;
4819}
4820
Geoff Langff5b2d52016-09-07 11:32:23 -04004821bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4822 GLenum target,
4823 GLenum attachment,
4824 GLenum pname,
4825 GLsizei *numParams)
4826{
4827 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4828 *numParams = 1;
4829
4830 if (!ValidFramebufferTarget(target))
4831 {
4832 context->handleError(Error(GL_INVALID_ENUM));
4833 return false;
4834 }
4835
4836 int clientVersion = context->getClientMajorVersion();
4837
4838 switch (pname)
4839 {
4840 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4841 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4842 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4843 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4844 break;
4845
4846 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4847 if (clientVersion < 3 && !context->getExtensions().sRGB)
4848 {
4849 context->handleError(Error(GL_INVALID_ENUM));
4850 return false;
4851 }
4852 break;
4853
4854 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4855 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4856 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4857 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4858 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4859 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4860 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4861 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4862 if (clientVersion < 3)
4863 {
4864 context->handleError(Error(GL_INVALID_ENUM));
4865 return false;
4866 }
4867 break;
4868
4869 default:
4870 context->handleError(Error(GL_INVALID_ENUM));
4871 return false;
4872 }
4873
4874 // Determine if the attachment is a valid enum
4875 switch (attachment)
4876 {
4877 case GL_BACK:
4878 case GL_FRONT:
4879 case GL_DEPTH:
4880 case GL_STENCIL:
4881 case GL_DEPTH_STENCIL_ATTACHMENT:
4882 if (clientVersion < 3)
4883 {
4884 context->handleError(Error(GL_INVALID_ENUM));
4885 return false;
4886 }
4887 break;
4888
4889 case GL_DEPTH_ATTACHMENT:
4890 case GL_STENCIL_ATTACHMENT:
4891 break;
4892
4893 default:
4894 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4895 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4896 {
4897 context->handleError(Error(GL_INVALID_ENUM));
4898 return false;
4899 }
4900 break;
4901 }
4902
4903 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4904 ASSERT(framebuffer);
4905
4906 if (framebuffer->id() == 0)
4907 {
4908 if (clientVersion < 3)
4909 {
4910 context->handleError(Error(GL_INVALID_OPERATION));
4911 return false;
4912 }
4913
4914 switch (attachment)
4915 {
4916 case GL_BACK:
4917 case GL_DEPTH:
4918 case GL_STENCIL:
4919 break;
4920
4921 default:
4922 context->handleError(Error(GL_INVALID_OPERATION));
4923 return false;
4924 }
4925 }
4926 else
4927 {
4928 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4929 {
4930 // Valid attachment query
4931 }
4932 else
4933 {
4934 switch (attachment)
4935 {
4936 case GL_DEPTH_ATTACHMENT:
4937 case GL_STENCIL_ATTACHMENT:
4938 break;
4939
4940 case GL_DEPTH_STENCIL_ATTACHMENT:
4941 if (!framebuffer->hasValidDepthStencil())
4942 {
4943 context->handleError(Error(GL_INVALID_OPERATION));
4944 return false;
4945 }
4946 break;
4947
4948 default:
4949 context->handleError(Error(GL_INVALID_OPERATION));
4950 return false;
4951 }
4952 }
4953 }
4954
4955 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4956 if (attachmentObject)
4957 {
4958 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4959 attachmentObject->type() == GL_TEXTURE ||
4960 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4961
4962 switch (pname)
4963 {
4964 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4965 if (attachmentObject->type() != GL_RENDERBUFFER &&
4966 attachmentObject->type() != GL_TEXTURE)
4967 {
4968 context->handleError(Error(GL_INVALID_ENUM));
4969 return false;
4970 }
4971 break;
4972
4973 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4974 if (attachmentObject->type() != GL_TEXTURE)
4975 {
4976 context->handleError(Error(GL_INVALID_ENUM));
4977 return false;
4978 }
4979 break;
4980
4981 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4982 if (attachmentObject->type() != GL_TEXTURE)
4983 {
4984 context->handleError(Error(GL_INVALID_ENUM));
4985 return false;
4986 }
4987 break;
4988
4989 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4990 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4991 {
4992 context->handleError(Error(GL_INVALID_OPERATION));
4993 return false;
4994 }
4995 break;
4996
4997 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4998 if (attachmentObject->type() != GL_TEXTURE)
4999 {
5000 context->handleError(Error(GL_INVALID_ENUM));
5001 return false;
5002 }
5003 break;
5004
5005 default:
5006 break;
5007 }
5008 }
5009 else
5010 {
5011 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
5012 // is NONE, then querying any other pname will generate INVALID_ENUM.
5013
5014 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
5015 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
5016 // INVALID_OPERATION for all other pnames
5017
5018 switch (pname)
5019 {
5020 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5021 break;
5022
5023 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5024 if (clientVersion < 3)
5025 {
5026 context->handleError(Error(GL_INVALID_ENUM));
5027 return false;
5028 }
5029 break;
5030
5031 default:
5032 if (clientVersion < 3)
5033 {
5034 context->handleError(Error(GL_INVALID_ENUM));
5035 return false;
5036 }
5037 else
5038 {
5039 context->handleError(Error(GL_INVALID_OPERATION));
5040 return false;
5041 }
5042 }
5043 }
5044
5045 return true;
5046}
5047
5048bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5049 GLenum target,
5050 GLenum attachment,
5051 GLenum pname,
5052 GLsizei bufSize,
5053 GLsizei *numParams)
5054{
5055 if (!ValidateRobustEntryPoint(context, bufSize))
5056 {
5057 return false;
5058 }
5059
5060 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5061 {
5062 return false;
5063 }
5064
5065 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5066 {
5067 return false;
5068 }
5069
5070 return true;
5071}
5072
5073bool ValidateGetBufferParameteriv(ValidationContext *context,
5074 GLenum target,
5075 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005076 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005077{
Geoff Langebebe1c2016-10-14 12:01:31 -04005078 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005079}
5080
5081bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5082 GLenum target,
5083 GLenum pname,
5084 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005085 GLsizei *length,
5086 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005087{
5088 if (!ValidateRobustEntryPoint(context, bufSize))
5089 {
5090 return false;
5091 }
5092
Geoff Langebebe1c2016-10-14 12:01:31 -04005093 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005094 {
5095 return false;
5096 }
5097
Geoff Langebebe1c2016-10-14 12:01:31 -04005098 if (!ValidateRobustBufferSize(context, bufSize, *length))
5099 {
5100 return false;
5101 }
5102
5103 return true;
5104}
5105
5106bool ValidateGetBufferParameteri64v(ValidationContext *context,
5107 GLenum target,
5108 GLenum pname,
5109 GLint64 *params)
5110{
5111 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5112}
5113
5114bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5115 GLenum target,
5116 GLenum pname,
5117 GLsizei bufSize,
5118 GLsizei *length,
5119 GLint64 *params)
5120{
5121 if (!ValidateRobustEntryPoint(context, bufSize))
5122 {
5123 return false;
5124 }
5125
5126 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5127 {
5128 return false;
5129 }
5130
5131 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005132 {
5133 return false;
5134 }
5135
5136 return true;
5137}
5138
5139bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5140{
5141 // Currently, all GetProgramiv queries return 1 parameter
5142 *numParams = 1;
5143
5144 Program *programObject = GetValidProgram(context, program);
5145 if (!programObject)
5146 {
5147 return false;
5148 }
5149
5150 switch (pname)
5151 {
5152 case GL_DELETE_STATUS:
5153 case GL_LINK_STATUS:
5154 case GL_VALIDATE_STATUS:
5155 case GL_INFO_LOG_LENGTH:
5156 case GL_ATTACHED_SHADERS:
5157 case GL_ACTIVE_ATTRIBUTES:
5158 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5159 case GL_ACTIVE_UNIFORMS:
5160 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5161 break;
5162
5163 case GL_PROGRAM_BINARY_LENGTH:
5164 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5165 {
5166 context->handleError(Error(GL_INVALID_ENUM,
5167 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5168 "GL_OES_get_program_binary or ES 3.0."));
5169 return false;
5170 }
5171 break;
5172
5173 case GL_ACTIVE_UNIFORM_BLOCKS:
5174 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5175 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5176 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5177 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5178 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5179 if (context->getClientMajorVersion() < 3)
5180 {
5181 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5182 return false;
5183 }
5184 break;
5185
5186 default:
5187 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5188 return false;
5189 }
5190
5191 return true;
5192}
5193
5194bool ValidateGetProgramivRobustANGLE(Context *context,
5195 GLuint program,
5196 GLenum pname,
5197 GLsizei bufSize,
5198 GLsizei *numParams)
5199{
5200 if (!ValidateRobustEntryPoint(context, bufSize))
5201 {
5202 return false;
5203 }
5204
5205 if (!ValidateGetProgramiv(context, program, pname, numParams))
5206 {
5207 return false;
5208 }
5209
5210 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5211 {
5212 return false;
5213 }
5214
5215 return true;
5216}
5217
Geoff Lang740d9022016-10-07 11:20:52 -04005218bool ValidateGetRenderbufferParameteriv(Context *context,
5219 GLenum target,
5220 GLenum pname,
5221 GLint *params)
5222{
5223 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5224}
5225
5226bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5227 GLenum target,
5228 GLenum pname,
5229 GLsizei bufSize,
5230 GLsizei *length,
5231 GLint *params)
5232{
5233 if (!ValidateRobustEntryPoint(context, bufSize))
5234 {
5235 return false;
5236 }
5237
5238 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5239 {
5240 return false;
5241 }
5242
5243 if (!ValidateRobustBufferSize(context, bufSize, *length))
5244 {
5245 return false;
5246 }
5247
5248 return true;
5249}
5250
Geoff Langd7d0ed32016-10-07 11:33:51 -04005251bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5252{
5253 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5254}
5255
5256bool ValidateGetShaderivRobustANGLE(Context *context,
5257 GLuint shader,
5258 GLenum pname,
5259 GLsizei bufSize,
5260 GLsizei *length,
5261 GLint *params)
5262{
5263 if (!ValidateRobustEntryPoint(context, bufSize))
5264 {
5265 return false;
5266 }
5267
5268 if (!ValidateGetShaderivBase(context, shader, pname, length))
5269 {
5270 return false;
5271 }
5272
5273 if (!ValidateRobustBufferSize(context, bufSize, *length))
5274 {
5275 return false;
5276 }
5277
5278 return true;
5279}
5280
Geoff Langc1984ed2016-10-07 12:41:00 -04005281bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5282{
5283 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5284}
5285
5286bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5287 GLenum target,
5288 GLenum pname,
5289 GLsizei bufSize,
5290 GLsizei *length,
5291 GLfloat *params)
5292{
5293 if (!ValidateRobustEntryPoint(context, bufSize))
5294 {
5295 return false;
5296 }
5297
5298 if (!ValidateGetTexParameterBase(context, target, pname, length))
5299 {
5300 return false;
5301 }
5302
5303 if (!ValidateRobustBufferSize(context, bufSize, *length))
5304 {
5305 return false;
5306 }
5307
5308 return true;
5309}
5310
5311bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5312{
5313 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5314}
5315
5316bool ValidateGetTexParameterivRobustANGLE(Context *context,
5317 GLenum target,
5318 GLenum pname,
5319 GLsizei bufSize,
5320 GLsizei *length,
5321 GLint *params)
5322{
5323 if (!ValidateRobustEntryPoint(context, bufSize))
5324 {
5325 return false;
5326 }
5327
5328 if (!ValidateGetTexParameterBase(context, target, pname, length))
5329 {
5330 return false;
5331 }
5332
5333 if (!ValidateRobustBufferSize(context, bufSize, *length))
5334 {
5335 return false;
5336 }
5337
5338 return true;
5339}
5340
5341bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5342{
5343 return ValidateTexParameterBase(context, target, pname, -1, &param);
5344}
5345
5346bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5347{
5348 return ValidateTexParameterBase(context, target, pname, -1, params);
5349}
5350
5351bool ValidateTexParameterfvRobustANGLE(Context *context,
5352 GLenum target,
5353 GLenum pname,
5354 GLsizei bufSize,
5355 const GLfloat *params)
5356{
5357 if (!ValidateRobustEntryPoint(context, bufSize))
5358 {
5359 return false;
5360 }
5361
5362 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5363}
5364
5365bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5366{
5367 return ValidateTexParameterBase(context, target, pname, -1, &param);
5368}
5369
5370bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5371{
5372 return ValidateTexParameterBase(context, target, pname, -1, params);
5373}
5374
5375bool ValidateTexParameterivRobustANGLE(Context *context,
5376 GLenum target,
5377 GLenum pname,
5378 GLsizei bufSize,
5379 const GLint *params)
5380{
5381 if (!ValidateRobustEntryPoint(context, bufSize))
5382 {
5383 return false;
5384 }
5385
5386 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5387}
5388
5389bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5390{
5391 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5392}
5393
5394bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5395 GLuint sampler,
5396 GLenum pname,
5397 GLuint bufSize,
5398 GLsizei *length,
5399 GLfloat *params)
5400{
5401 if (!ValidateRobustEntryPoint(context, bufSize))
5402 {
5403 return false;
5404 }
5405
5406 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5407 {
5408 return false;
5409 }
5410
5411 if (!ValidateRobustBufferSize(context, bufSize, *length))
5412 {
5413 return false;
5414 }
5415
5416 return true;
5417}
5418
5419bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5420{
5421 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5422}
5423
5424bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5425 GLuint sampler,
5426 GLenum pname,
5427 GLuint bufSize,
5428 GLsizei *length,
5429 GLint *params)
5430{
5431 if (!ValidateRobustEntryPoint(context, bufSize))
5432 {
5433 return false;
5434 }
5435
5436 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5437 {
5438 return false;
5439 }
5440
5441 if (!ValidateRobustBufferSize(context, bufSize, *length))
5442 {
5443 return false;
5444 }
5445
5446 return true;
5447}
5448
5449bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5450{
5451 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5452}
5453
5454bool ValidateSamplerParameterfv(Context *context,
5455 GLuint sampler,
5456 GLenum pname,
5457 const GLfloat *params)
5458{
5459 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5460}
5461
5462bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5463 GLuint sampler,
5464 GLenum pname,
5465 GLsizei bufSize,
5466 const GLfloat *params)
5467{
5468 if (!ValidateRobustEntryPoint(context, bufSize))
5469 {
5470 return false;
5471 }
5472
5473 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5474}
5475
5476bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5477{
5478 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5479}
5480
5481bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5482{
5483 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5484}
5485
5486bool ValidateSamplerParameterivRobustANGLE(Context *context,
5487 GLuint sampler,
5488 GLenum pname,
5489 GLsizei bufSize,
5490 const GLint *params)
5491{
5492 if (!ValidateRobustEntryPoint(context, bufSize))
5493 {
5494 return false;
5495 }
5496
5497 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5498}
5499
Geoff Lang0b031062016-10-13 14:30:04 -04005500bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5501{
5502 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5503}
5504
5505bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5506 GLuint index,
5507 GLenum pname,
5508 GLsizei bufSize,
5509 GLsizei *length,
5510 GLfloat *params)
5511{
5512 if (!ValidateRobustEntryPoint(context, bufSize))
5513 {
5514 return false;
5515 }
5516
5517 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5518 {
5519 return false;
5520 }
5521
5522 if (!ValidateRobustBufferSize(context, bufSize, *length))
5523 {
5524 return false;
5525 }
5526
5527 return true;
5528}
5529
5530bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5531{
5532 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5533}
5534
5535bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5536 GLuint index,
5537 GLenum pname,
5538 GLsizei bufSize,
5539 GLsizei *length,
5540 GLint *params)
5541{
5542 if (!ValidateRobustEntryPoint(context, bufSize))
5543 {
5544 return false;
5545 }
5546
5547 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5548 {
5549 return false;
5550 }
5551
5552 if (!ValidateRobustBufferSize(context, bufSize, *length))
5553 {
5554 return false;
5555 }
5556
5557 return true;
5558}
5559
5560bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5561{
5562 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5563}
5564
5565bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5566 GLuint index,
5567 GLenum pname,
5568 GLsizei bufSize,
5569 GLsizei *length,
5570 void **pointer)
5571{
5572 if (!ValidateRobustEntryPoint(context, bufSize))
5573 {
5574 return false;
5575 }
5576
5577 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5578 {
5579 return false;
5580 }
5581
5582 if (!ValidateRobustBufferSize(context, bufSize, *length))
5583 {
5584 return false;
5585 }
5586
5587 return true;
5588}
5589
5590bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5591{
5592 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5593}
5594
5595bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5596 GLuint index,
5597 GLenum pname,
5598 GLsizei bufSize,
5599 GLsizei *length,
5600 GLint *params)
5601{
5602 if (!ValidateRobustEntryPoint(context, bufSize))
5603 {
5604 return false;
5605 }
5606
5607 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5608 {
5609 return false;
5610 }
5611
5612 if (!ValidateRobustBufferSize(context, bufSize, *length))
5613 {
5614 return false;
5615 }
5616
5617 return true;
5618}
5619
5620bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5621{
5622 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5623}
5624
5625bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5626 GLuint index,
5627 GLenum pname,
5628 GLsizei bufSize,
5629 GLsizei *length,
5630 GLuint *params)
5631{
5632 if (!ValidateRobustEntryPoint(context, bufSize))
5633 {
5634 return false;
5635 }
5636
5637 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5638 {
5639 return false;
5640 }
5641
5642 if (!ValidateRobustBufferSize(context, bufSize, *length))
5643 {
5644 return false;
5645 }
5646
5647 return true;
5648}
5649
Geoff Lang6899b872016-10-14 11:30:13 -04005650bool ValidateGetActiveUniformBlockiv(Context *context,
5651 GLuint program,
5652 GLuint uniformBlockIndex,
5653 GLenum pname,
5654 GLint *params)
5655{
5656 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5657}
5658
5659bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5660 GLuint program,
5661 GLuint uniformBlockIndex,
5662 GLenum pname,
5663 GLsizei bufSize,
5664 GLsizei *length,
5665 GLint *params)
5666{
5667 if (!ValidateRobustEntryPoint(context, bufSize))
5668 {
5669 return false;
5670 }
5671
5672 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5673 {
5674 return false;
5675 }
5676
5677 if (!ValidateRobustBufferSize(context, bufSize, *length))
5678 {
5679 return false;
5680 }
5681
5682 return true;
5683}
5684
Geoff Lang0a9661f2016-10-20 10:59:20 -07005685bool ValidateGetInternalFormativ(Context *context,
5686 GLenum target,
5687 GLenum internalformat,
5688 GLenum pname,
5689 GLsizei bufSize,
5690 GLint *params)
5691{
5692 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5693 nullptr);
5694}
5695
5696bool ValidateGetInternalFormativRobustANGLE(Context *context,
5697 GLenum target,
5698 GLenum internalformat,
5699 GLenum pname,
5700 GLsizei bufSize,
5701 GLsizei *length,
5702 GLint *params)
5703{
5704 if (!ValidateRobustEntryPoint(context, bufSize))
5705 {
5706 return false;
5707 }
5708
5709 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5710 {
5711 return false;
5712 }
5713
5714 if (!ValidateRobustBufferSize(context, bufSize, *length))
5715 {
5716 return false;
5717 }
5718
5719 return true;
5720}
5721
Jamie Madillc29968b2016-01-20 11:17:23 -05005722} // namespace gl