blob: f11c1f7009f268144fa3c231c65ec15de382c40d [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
Geoff Langf41a7152016-09-19 15:11:17 -04001361} // anonymous namespace
1362
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001363bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001364{
Jamie Madilld7460c72014-01-21 16:38:14 -05001365 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001366 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001367 case GL_TEXTURE_2D:
1368 case GL_TEXTURE_CUBE_MAP:
1369 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001370
He Yunchaoced53ae2016-11-29 15:00:51 +08001371 case GL_TEXTURE_3D:
1372 case GL_TEXTURE_2D_ARRAY:
1373 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001374
He Yunchaoced53ae2016-11-29 15:00:51 +08001375 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001376 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001377
He Yunchaoced53ae2016-11-29 15:00:51 +08001378 default:
1379 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001380 }
Jamie Madill35d15012013-10-07 10:46:37 -04001381}
1382
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001383bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1384{
1385 switch (target)
1386 {
1387 case GL_TEXTURE_2D:
1388 case GL_TEXTURE_CUBE_MAP:
1389 return true;
1390
1391 default:
1392 return false;
1393 }
1394}
1395
1396bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1397{
1398 switch (target)
1399 {
1400 case GL_TEXTURE_3D:
1401 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001402 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001403
1404 default:
1405 return false;
1406 }
1407}
1408
Ian Ewellbda75592016-04-18 17:25:54 -04001409// Most texture GL calls are not compatible with external textures, so we have a separate validation
1410// function for use in the GL calls that do
1411bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1412{
1413 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1414 (context->getExtensions().eglImageExternal ||
1415 context->getExtensions().eglStreamConsumerExternal);
1416}
1417
Shannon Woods4dfed832014-03-17 20:03:39 -04001418// This function differs from ValidTextureTarget in that the target must be
1419// usable as the destination of a 2D operation-- so a cube face is valid, but
1420// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001421// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001422bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001423{
1424 switch (target)
1425 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001426 case GL_TEXTURE_2D:
1427 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1428 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1429 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1430 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1431 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1432 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1433 return true;
1434 default:
1435 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001436 }
1437}
1438
1439bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1440{
1441 switch (target)
1442 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001443 case GL_TEXTURE_3D:
1444 case GL_TEXTURE_2D_ARRAY:
1445 return true;
1446 default:
1447 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001448 }
1449}
1450
He Yunchao11b038b2016-11-22 21:24:04 +08001451bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1452{
1453 switch (target)
1454 {
1455 case GL_TEXTURE_2D:
1456 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1457 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1458 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1459 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1460 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1461 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1462 case GL_TEXTURE_3D:
1463 case GL_TEXTURE_2D_ARRAY:
1464 case GL_TEXTURE_2D_MULTISAMPLE:
1465 return true;
1466 default:
1467 return false;
1468 }
1469}
1470
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001471bool ValidFramebufferTarget(GLenum target)
1472{
He Yunchaoced53ae2016-11-29 15:00:51 +08001473 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1474 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001475 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001476
1477 switch (target)
1478 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001479 case GL_FRAMEBUFFER:
1480 return true;
1481 case GL_READ_FRAMEBUFFER:
1482 return true;
1483 case GL_DRAW_FRAMEBUFFER:
1484 return true;
1485 default:
1486 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001487 }
1488}
1489
Jamie Madill29639852016-09-02 15:00:09 -04001490bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001491{
1492 switch (target)
1493 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001494 case GL_ARRAY_BUFFER:
1495 case GL_ELEMENT_ARRAY_BUFFER:
1496 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001497
He Yunchaoced53ae2016-11-29 15:00:51 +08001498 case GL_PIXEL_PACK_BUFFER:
1499 case GL_PIXEL_UNPACK_BUFFER:
1500 return (context->getExtensions().pixelBufferObject ||
1501 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001502
He Yunchaoced53ae2016-11-29 15:00:51 +08001503 case GL_COPY_READ_BUFFER:
1504 case GL_COPY_WRITE_BUFFER:
1505 case GL_TRANSFORM_FEEDBACK_BUFFER:
1506 case GL_UNIFORM_BUFFER:
1507 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001508
He Yunchaoced53ae2016-11-29 15:00:51 +08001509 case GL_ATOMIC_COUNTER_BUFFER:
1510 case GL_SHADER_STORAGE_BUFFER:
1511 case GL_DRAW_INDIRECT_BUFFER:
1512 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001513 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001514
He Yunchaoced53ae2016-11-29 15:00:51 +08001515 default:
1516 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001517 }
1518}
1519
Jamie Madillc29968b2016-01-20 11:17:23 -05001520bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001521{
Jamie Madillc29968b2016-01-20 11:17:23 -05001522 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001523 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001524 switch (target)
1525 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001526 case GL_TEXTURE_2D:
1527 maxDimension = caps.max2DTextureSize;
1528 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001529 case GL_TEXTURE_CUBE_MAP:
1530 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1531 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1532 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1533 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1534 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1535 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1536 maxDimension = caps.maxCubeMapTextureSize;
1537 break;
1538 case GL_TEXTURE_3D:
1539 maxDimension = caps.max3DTextureSize;
1540 break;
1541 case GL_TEXTURE_2D_ARRAY:
1542 maxDimension = caps.max2DTextureSize;
1543 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001544 case GL_TEXTURE_2D_MULTISAMPLE:
1545 maxDimension = caps.max2DTextureSize;
1546 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001547 default:
1548 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001549 }
1550
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001551 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001552}
1553
Geoff Langcc507aa2016-12-12 10:09:52 -05001554bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001555 GLenum target,
1556 GLint level,
1557 GLsizei width,
1558 GLsizei height,
1559 GLsizei depth,
1560 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001561{
1562 if (level < 0 || width < 0 || height < 0 || depth < 0)
1563 {
1564 return false;
1565 }
1566
Austin Kinross08528e12015-10-07 16:24:40 -07001567 // TexSubImage parameters can be NPOT without textureNPOT extension,
1568 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001569 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001570 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001571 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001572 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001573 {
1574 return false;
1575 }
1576
1577 if (!ValidMipLevel(context, target, level))
1578 {
1579 return false;
1580 }
1581
1582 return true;
1583}
1584
Geoff Lang0d8b7242015-09-09 14:56:53 -04001585bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1586{
1587 // List of compressed format that require that the texture size is smaller than or a multiple of
1588 // the compressed block size.
1589 switch (internalFormat)
1590 {
1591 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1592 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1593 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1594 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001595 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001596 return true;
1597
1598 default:
1599 return false;
1600 }
1601}
1602
Jamie Madillc29968b2016-01-20 11:17:23 -05001603bool ValidCompressedImageSize(const ValidationContext *context,
1604 GLenum internalFormat,
1605 GLsizei width,
1606 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001607{
Geoff Lang5d601382014-07-22 15:14:06 -04001608 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1609 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001610 {
1611 return false;
1612 }
1613
Geoff Lang0d8b7242015-09-09 14:56:53 -04001614 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001615 {
1616 return false;
1617 }
1618
Geoff Lang0d8b7242015-09-09 14:56:53 -04001619 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1620 {
1621 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1622 width % formatInfo.compressedBlockWidth != 0) ||
1623 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1624 height % formatInfo.compressedBlockHeight != 0))
1625 {
1626 return false;
1627 }
1628 }
1629
Geoff Langd4f180b2013-09-24 13:57:44 -04001630 return true;
1631}
1632
Geoff Langff5b2d52016-09-07 11:32:23 -04001633bool ValidImageDataSize(ValidationContext *context,
1634 GLenum textureTarget,
1635 GLsizei width,
1636 GLsizei height,
1637 GLsizei depth,
1638 GLenum internalFormat,
1639 GLenum type,
1640 const GLvoid *pixels,
1641 GLsizei imageSize)
1642{
1643 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1644 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1645 {
1646 // Checks are not required
1647 return true;
1648 }
1649
1650 // ...the data would be unpacked from the buffer object such that the memory reads required
1651 // would exceed the data store size.
1652 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1653 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1654 const gl::Extents size(width, height, depth);
1655 const auto &unpack = context->getGLState().getUnpackState();
1656
1657 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1658 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1659 if (endByteOrErr.isError())
1660 {
1661 context->handleError(endByteOrErr.getError());
1662 return false;
1663 }
1664
1665 GLuint endByte = endByteOrErr.getResult();
1666
1667 if (pixelUnpackBuffer)
1668 {
1669 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1670 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1671 checkedEndByte += checkedOffset;
1672
1673 if (!checkedEndByte.IsValid() ||
1674 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1675 {
1676 // Overflow past the end of the buffer
1677 context->handleError(Error(GL_INVALID_OPERATION));
1678 return false;
1679 }
1680 }
1681 else
1682 {
1683 ASSERT(imageSize >= 0);
1684 if (pixels == nullptr && imageSize != 0)
1685 {
1686 context->handleError(
1687 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001688 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001689 }
1690
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001691 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001692 {
1693 context->handleError(
1694 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1695 return false;
1696 }
1697 }
1698
1699 return true;
1700}
1701
Geoff Lang37dde692014-01-31 16:34:54 -05001702bool ValidQueryType(const Context *context, GLenum queryType)
1703{
He Yunchaoced53ae2016-11-29 15:00:51 +08001704 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1705 "GL extension enums not equal.");
1706 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1707 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001708
1709 switch (queryType)
1710 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001711 case GL_ANY_SAMPLES_PASSED:
1712 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1713 return true;
1714 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1715 return (context->getClientMajorVersion() >= 3);
1716 case GL_TIME_ELAPSED_EXT:
1717 return context->getExtensions().disjointTimerQuery;
1718 case GL_COMMANDS_COMPLETED_CHROMIUM:
1719 return context->getExtensions().syncQuery;
1720 default:
1721 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001722 }
1723}
1724
Jamie Madillef300b12016-10-07 15:12:09 -04001725Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001726{
He Yunchaoced53ae2016-11-29 15:00:51 +08001727 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1728 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1729 // or program object and INVALID_OPERATION if the provided name identifies an object
1730 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001731
Dian Xiang769769a2015-09-09 15:20:08 -07001732 Program *validProgram = context->getProgram(id);
1733
1734 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001735 {
Dian Xiang769769a2015-09-09 15:20:08 -07001736 if (context->getShader(id))
1737 {
Jamie Madill437fa652016-05-03 15:13:24 -04001738 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001739 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1740 }
1741 else
1742 {
Jamie Madill437fa652016-05-03 15:13:24 -04001743 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001744 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001745 }
Dian Xiang769769a2015-09-09 15:20:08 -07001746
1747 return validProgram;
1748}
1749
Jamie Madillef300b12016-10-07 15:12:09 -04001750Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001751{
1752 // See ValidProgram for spec details.
1753
1754 Shader *validShader = context->getShader(id);
1755
1756 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001757 {
Dian Xiang769769a2015-09-09 15:20:08 -07001758 if (context->getProgram(id))
1759 {
Jamie Madill437fa652016-05-03 15:13:24 -04001760 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001761 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1762 }
1763 else
1764 {
Jamie Madill437fa652016-05-03 15:13:24 -04001765 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001766 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001767 }
Dian Xiang769769a2015-09-09 15:20:08 -07001768
1769 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001770}
1771
Geoff Langb1196682014-07-23 13:47:29 -04001772bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001773{
1774 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1775 {
1776 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1777
Geoff Langaae65a42014-05-26 12:43:44 -04001778 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001779 {
Jamie Madill437fa652016-05-03 15:13:24 -04001780 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001781 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001782 }
1783 }
1784 else
1785 {
1786 switch (attachment)
1787 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001788 case GL_DEPTH_ATTACHMENT:
1789 case GL_STENCIL_ATTACHMENT:
1790 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001791
He Yunchaoced53ae2016-11-29 15:00:51 +08001792 case GL_DEPTH_STENCIL_ATTACHMENT:
1793 if (!context->getExtensions().webglCompatibility &&
1794 context->getClientMajorVersion() < 3)
1795 {
1796 context->handleError(Error(GL_INVALID_ENUM));
1797 return false;
1798 }
1799 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001800
He Yunchaoced53ae2016-11-29 15:00:51 +08001801 default:
1802 context->handleError(Error(GL_INVALID_ENUM));
1803 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001804 }
1805 }
1806
1807 return true;
1808}
1809
He Yunchaoced53ae2016-11-29 15:00:51 +08001810bool ValidateRenderbufferStorageParametersBase(gl::Context *context,
1811 GLenum target,
1812 GLsizei samples,
1813 GLenum internalformat,
1814 GLsizei width,
1815 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001816{
1817 switch (target)
1818 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001819 case GL_RENDERBUFFER:
1820 break;
1821 default:
1822 context->handleError(Error(GL_INVALID_ENUM));
1823 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001824 }
1825
1826 if (width < 0 || height < 0 || samples < 0)
1827 {
Jamie Madill437fa652016-05-03 15:13:24 -04001828 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001829 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001830 }
1831
Geoff Langd87878e2014-09-19 15:42:59 -04001832 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1833 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001834 {
Jamie Madill437fa652016-05-03 15:13:24 -04001835 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001836 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001837 }
1838
1839 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1840 // 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 -08001841 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001842 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001843 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001844 {
Jamie Madill437fa652016-05-03 15:13:24 -04001845 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001846 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001847 }
1848
Geoff Langaae65a42014-05-26 12:43:44 -04001849 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001850 {
Jamie Madill437fa652016-05-03 15:13:24 -04001851 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001852 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001853 }
1854
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001855 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001856 if (handle == 0)
1857 {
Jamie Madill437fa652016-05-03 15:13:24 -04001858 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001859 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001860 }
1861
1862 return true;
1863}
1864
He Yunchaoced53ae2016-11-29 15:00:51 +08001865bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context,
1866 GLenum target,
1867 GLsizei samples,
1868 GLenum internalformat,
1869 GLsizei width,
1870 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -08001871{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001872 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001873
1874 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001875 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001876 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001877 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001878 {
Jamie Madill437fa652016-05-03 15:13:24 -04001879 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001880 return false;
1881 }
1882
1883 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1884 // the specified storage. This is different than ES 3.0 in which a sample number higher
1885 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001886 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001887 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001888 {
Geoff Langa4903b72015-03-02 16:02:48 -08001889 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1890 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1891 {
Jamie Madill437fa652016-05-03 15:13:24 -04001892 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001893 return false;
1894 }
Corentin Walleze0902642014-11-04 12:32:15 -08001895 }
1896
He Yunchaoced53ae2016-11-29 15:00:51 +08001897 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
1898 width, height);
Corentin Walleze0902642014-11-04 12:32:15 -08001899}
1900
He Yunchaoced53ae2016-11-29 15:00:51 +08001901bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1902 GLenum target,
1903 GLenum attachment,
1904 GLenum renderbuffertarget,
1905 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001906{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001907 if (!ValidFramebufferTarget(target))
1908 {
Jamie Madill437fa652016-05-03 15:13:24 -04001909 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001910 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001911 }
1912
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001913 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001914
Jamie Madill84115c92015-04-23 15:00:07 -04001915 ASSERT(framebuffer);
1916 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001917 {
Jamie Madill437fa652016-05-03 15:13:24 -04001918 context->handleError(
1919 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001920 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001921 }
1922
Jamie Madillb4472272014-07-03 10:38:55 -04001923 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001924 {
Jamie Madillb4472272014-07-03 10:38:55 -04001925 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001926 }
1927
Jamie Madillab9d82c2014-01-21 16:38:14 -05001928 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1929 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1930 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1931 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1932 if (renderbuffer != 0)
1933 {
1934 if (!context->getRenderbuffer(renderbuffer))
1935 {
Jamie Madill437fa652016-05-03 15:13:24 -04001936 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001937 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001938 }
1939 }
1940
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001941 return true;
1942}
1943
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001944bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001945 GLint srcX0,
1946 GLint srcY0,
1947 GLint srcX1,
1948 GLint srcY1,
1949 GLint dstX0,
1950 GLint dstY0,
1951 GLint dstX1,
1952 GLint dstY1,
1953 GLbitfield mask,
1954 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001955{
1956 switch (filter)
1957 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001958 case GL_NEAREST:
1959 break;
1960 case GL_LINEAR:
1961 break;
1962 default:
1963 context->handleError(Error(GL_INVALID_ENUM));
1964 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001965 }
1966
1967 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1968 {
Jamie Madill437fa652016-05-03 15:13:24 -04001969 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001970 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001971 }
1972
1973 if (mask == 0)
1974 {
1975 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1976 // buffers are copied.
1977 return false;
1978 }
1979
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001980 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1981 // color buffer, leaving only nearest being unfiltered from above
1982 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1983 {
Jamie Madill437fa652016-05-03 15:13:24 -04001984 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001985 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001986 }
1987
Jamie Madill51f40ec2016-06-15 14:06:00 -04001988 const auto &glState = context->getGLState();
1989 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1990 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001991
1992 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001993 {
Jamie Madill437fa652016-05-03 15:13:24 -04001994 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001995 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001996 }
1997
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001998 if (readFramebuffer->id() == drawFramebuffer->id())
1999 {
2000 context->handleError(Error(GL_INVALID_OPERATION));
2001 return false;
2002 }
2003
Jamie Madill51f40ec2016-06-15 14:06:00 -04002004 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002005 {
Jamie Madill437fa652016-05-03 15:13:24 -04002006 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002007 return false;
2008 }
2009
Jamie Madill51f40ec2016-06-15 14:06:00 -04002010 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002011 {
Jamie Madill437fa652016-05-03 15:13:24 -04002012 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002013 return false;
2014 }
2015
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002016 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002017 {
Jamie Madill437fa652016-05-03 15:13:24 -04002018 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002019 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002020 }
2021
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002022 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2023
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002024 if (mask & GL_COLOR_BUFFER_BIT)
2025 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002026 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002027 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002028
He Yunchao66a41a22016-12-15 16:45:05 +08002029 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002030 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002031 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002032
Geoff Langa15472a2015-08-11 11:48:03 -04002033 for (size_t drawbufferIdx = 0;
2034 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002035 {
Geoff Langa15472a2015-08-11 11:48:03 -04002036 const FramebufferAttachment *attachment =
2037 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2038 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002039 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002040 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002041
Geoff Langb2f3d052013-08-13 12:49:27 -04002042 // The GL ES 3.0.2 spec (pg 193) states that:
2043 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002044 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2045 // as well
2046 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2047 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002048 // Changes with EXT_color_buffer_float:
2049 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002050 GLenum readComponentType = readFormat.info->componentType;
2051 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002052 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002053 readComponentType == GL_SIGNED_NORMALIZED);
2054 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2055 drawComponentType == GL_SIGNED_NORMALIZED);
2056
2057 if (extensions.colorBufferFloat)
2058 {
2059 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2060 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2061
2062 if (readFixedOrFloat != drawFixedOrFloat)
2063 {
Jamie Madill437fa652016-05-03 15:13:24 -04002064 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002065 "If the read buffer contains fixed-point or "
2066 "floating-point values, the draw buffer "
2067 "must as well."));
2068 return false;
2069 }
2070 }
2071 else if (readFixedPoint != drawFixedPoint)
2072 {
Jamie Madill437fa652016-05-03 15:13:24 -04002073 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002074 "If the read buffer contains fixed-point "
2075 "values, the draw buffer must as well."));
2076 return false;
2077 }
2078
2079 if (readComponentType == GL_UNSIGNED_INT &&
2080 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002081 {
Jamie Madill437fa652016-05-03 15:13:24 -04002082 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002083 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002084 }
2085
Jamie Madill6163c752015-12-07 16:32:59 -05002086 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002087 {
Jamie Madill437fa652016-05-03 15:13:24 -04002088 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002089 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002090 }
2091
Jamie Madilla3944d42016-07-22 22:13:26 -04002092 if (readColorBuffer->getSamples() > 0 &&
2093 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002094 {
Jamie Madill437fa652016-05-03 15:13:24 -04002095 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002096 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002097 }
2098 }
2099 }
2100
Jamie Madilla3944d42016-07-22 22:13:26 -04002101 if ((readFormat.info->componentType == GL_INT ||
2102 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2103 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002104 {
Jamie Madill437fa652016-05-03 15:13:24 -04002105 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002106 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002107 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002108 }
He Yunchao66a41a22016-12-15 16:45:05 +08002109 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2110 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2111 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2112 // situation is an application error that would lead to a crash in ANGLE.
2113 else if (drawFramebuffer->hasEnabledDrawBuffer())
2114 {
2115 context->handleError(Error(
2116 GL_INVALID_OPERATION,
2117 "Attempt to read from a missing color attachment of a complete framebuffer."));
2118 return false;
2119 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002120 }
2121
He Yunchaoced53ae2016-11-29 15:00:51 +08002122 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002123 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2124 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002125 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002126 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002127 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002128 const gl::FramebufferAttachment *readBuffer =
2129 readFramebuffer->getAttachment(attachments[i]);
2130 const gl::FramebufferAttachment *drawBuffer =
2131 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002132
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002133 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002134 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002135 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002136 {
Jamie Madill437fa652016-05-03 15:13:24 -04002137 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002138 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002139 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002140
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002141 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002142 {
Jamie Madill437fa652016-05-03 15:13:24 -04002143 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002144 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002145 }
2146 }
He Yunchao66a41a22016-12-15 16:45:05 +08002147 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2148 else if (drawBuffer)
2149 {
2150 context->handleError(Error(GL_INVALID_OPERATION,
2151 "Attempt to read from a missing depth/stencil "
2152 "attachment of a complete framebuffer."));
2153 return false;
2154 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002155 }
2156 }
2157
2158 return true;
2159}
2160
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002161bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002162 GLint x,
2163 GLint y,
2164 GLsizei width,
2165 GLsizei height,
2166 GLenum format,
2167 GLenum type,
2168 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002169{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002170 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2171}
2172
2173bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2174 GLint x,
2175 GLint y,
2176 GLsizei width,
2177 GLsizei height,
2178 GLenum format,
2179 GLenum type,
2180 GLsizei bufSize,
2181 GLsizei *length,
2182 GLvoid *pixels)
2183{
2184 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002185 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002186 return false;
2187 }
2188
Geoff Lang62fce5b2016-09-30 10:46:35 -04002189 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2190 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002191 {
Geoff Langb1196682014-07-23 13:47:29 -04002192 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002193 }
2194
Geoff Lang62fce5b2016-09-30 10:46:35 -04002195 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002196 {
Geoff Langb1196682014-07-23 13:47:29 -04002197 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002198 }
2199
Jamie Madillc29968b2016-01-20 11:17:23 -05002200 return true;
2201}
2202
2203bool ValidateReadnPixelsEXT(Context *context,
2204 GLint x,
2205 GLint y,
2206 GLsizei width,
2207 GLsizei height,
2208 GLenum format,
2209 GLenum type,
2210 GLsizei bufSize,
2211 GLvoid *pixels)
2212{
2213 if (bufSize < 0)
2214 {
Jamie Madill437fa652016-05-03 15:13:24 -04002215 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002216 return false;
2217 }
2218
Geoff Lang62fce5b2016-09-30 10:46:35 -04002219 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2220 pixels);
2221}
Jamie Madill26e91952014-03-05 15:01:27 -05002222
Geoff Lang62fce5b2016-09-30 10:46:35 -04002223bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2224 GLint x,
2225 GLint y,
2226 GLsizei width,
2227 GLsizei height,
2228 GLenum format,
2229 GLenum type,
2230 GLsizei bufSize,
2231 GLsizei *length,
2232 GLvoid *data)
2233{
2234 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002235 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002236 return false;
2237 }
2238
Geoff Lang62fce5b2016-09-30 10:46:35 -04002239 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002240 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002241 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002242 }
2243
Geoff Lang62fce5b2016-09-30 10:46:35 -04002244 if (!ValidateRobustBufferSize(context, bufSize, *length))
2245 {
2246 return false;
2247 }
2248
2249 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002250}
2251
Olli Etuaho41997e72016-03-10 13:38:39 +02002252bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002253{
2254 if (!context->getExtensions().occlusionQueryBoolean &&
2255 !context->getExtensions().disjointTimerQuery)
2256 {
Jamie Madill437fa652016-05-03 15:13:24 -04002257 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002258 return false;
2259 }
2260
Olli Etuaho41997e72016-03-10 13:38:39 +02002261 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002262}
2263
Olli Etuaho41997e72016-03-10 13:38:39 +02002264bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002265{
2266 if (!context->getExtensions().occlusionQueryBoolean &&
2267 !context->getExtensions().disjointTimerQuery)
2268 {
Jamie Madill437fa652016-05-03 15:13:24 -04002269 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002270 return false;
2271 }
2272
Olli Etuaho41997e72016-03-10 13:38:39 +02002273 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002274}
2275
2276bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002277{
2278 if (!ValidQueryType(context, target))
2279 {
Jamie Madill437fa652016-05-03 15:13:24 -04002280 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002281 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002282 }
2283
2284 if (id == 0)
2285 {
Jamie Madill437fa652016-05-03 15:13:24 -04002286 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002287 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002288 }
2289
2290 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2291 // of zero, if the active query object name for <target> is non-zero (for the
2292 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2293 // the active query for either target is non-zero), if <id> is the name of an
2294 // existing query object whose type does not match <target>, or if <id> is the
2295 // active query object name for any query type, the error INVALID_OPERATION is
2296 // generated.
2297
2298 // Ensure no other queries are active
2299 // NOTE: If other queries than occlusion are supported, we will need to check
2300 // separately that:
2301 // a) The query ID passed is not the current active query for any target/type
2302 // b) There are no active queries for the requested target (and in the case
2303 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2304 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002305
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002306 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002307 {
Jamie Madill437fa652016-05-03 15:13:24 -04002308 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002309 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002310 }
2311
2312 Query *queryObject = context->getQuery(id, true, target);
2313
2314 // check that name was obtained with glGenQueries
2315 if (!queryObject)
2316 {
Jamie Madill437fa652016-05-03 15:13:24 -04002317 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002318 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002319 }
2320
2321 // check for type mismatch
2322 if (queryObject->getType() != target)
2323 {
Jamie Madill437fa652016-05-03 15:13:24 -04002324 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002325 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002326 }
2327
2328 return true;
2329}
2330
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002331bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2332{
2333 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002334 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002335 {
Jamie Madill437fa652016-05-03 15:13:24 -04002336 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002337 return false;
2338 }
2339
2340 return ValidateBeginQueryBase(context, target, id);
2341}
2342
2343bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002344{
2345 if (!ValidQueryType(context, target))
2346 {
Jamie Madill437fa652016-05-03 15:13:24 -04002347 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002348 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002349 }
2350
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002351 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002352
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002353 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002354 {
Jamie Madill437fa652016-05-03 15:13:24 -04002355 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002356 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002357 }
2358
Jamie Madill45c785d2014-05-13 14:09:34 -04002359 return true;
2360}
2361
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002362bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2363{
2364 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002365 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002366 {
Jamie Madill437fa652016-05-03 15:13:24 -04002367 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002368 return false;
2369 }
2370
2371 return ValidateEndQueryBase(context, target);
2372}
2373
2374bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2375{
2376 if (!context->getExtensions().disjointTimerQuery)
2377 {
Jamie Madill437fa652016-05-03 15:13:24 -04002378 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002379 return false;
2380 }
2381
2382 if (target != GL_TIMESTAMP_EXT)
2383 {
Jamie Madill437fa652016-05-03 15:13:24 -04002384 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002385 return false;
2386 }
2387
2388 Query *queryObject = context->getQuery(id, true, target);
2389 if (queryObject == nullptr)
2390 {
Jamie Madill437fa652016-05-03 15:13:24 -04002391 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002392 return false;
2393 }
2394
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002395 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002396 {
Jamie Madill437fa652016-05-03 15:13:24 -04002397 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002398 return false;
2399 }
2400
2401 return true;
2402}
2403
Geoff Lang2186c382016-10-14 10:54:54 -04002404bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002405{
Geoff Lang2186c382016-10-14 10:54:54 -04002406 if (numParams)
2407 {
2408 *numParams = 0;
2409 }
2410
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002411 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2412 {
Jamie Madill437fa652016-05-03 15:13:24 -04002413 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002414 return false;
2415 }
2416
2417 switch (pname)
2418 {
2419 case GL_CURRENT_QUERY_EXT:
2420 if (target == GL_TIMESTAMP_EXT)
2421 {
Jamie Madill437fa652016-05-03 15:13:24 -04002422 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002423 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2424 return false;
2425 }
2426 break;
2427 case GL_QUERY_COUNTER_BITS_EXT:
2428 if (!context->getExtensions().disjointTimerQuery ||
2429 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2430 {
Jamie Madill437fa652016-05-03 15:13:24 -04002431 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002432 return false;
2433 }
2434 break;
2435 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002436 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002437 return false;
2438 }
2439
Geoff Lang2186c382016-10-14 10:54:54 -04002440 if (numParams)
2441 {
2442 // All queries return only one value
2443 *numParams = 1;
2444 }
2445
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002446 return true;
2447}
2448
2449bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2450{
2451 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002452 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002453 {
Jamie Madill437fa652016-05-03 15:13:24 -04002454 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002455 return false;
2456 }
2457
Geoff Lang2186c382016-10-14 10:54:54 -04002458 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002459}
2460
Geoff Lang2186c382016-10-14 10:54:54 -04002461bool ValidateGetQueryivRobustANGLE(Context *context,
2462 GLenum target,
2463 GLenum pname,
2464 GLsizei bufSize,
2465 GLsizei *length,
2466 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002467{
Geoff Lang2186c382016-10-14 10:54:54 -04002468 if (!ValidateRobustEntryPoint(context, bufSize))
2469 {
2470 return false;
2471 }
2472
2473 if (!ValidateGetQueryivBase(context, target, pname, length))
2474 {
2475 return false;
2476 }
2477
2478 if (!ValidateRobustBufferSize(context, bufSize, *length))
2479 {
2480 return false;
2481 }
2482
2483 return true;
2484}
2485
2486bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2487{
2488 if (numParams)
2489 {
2490 *numParams = 0;
2491 }
2492
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002493 Query *queryObject = context->getQuery(id, false, GL_NONE);
2494
2495 if (!queryObject)
2496 {
Jamie Madill437fa652016-05-03 15:13:24 -04002497 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002498 return false;
2499 }
2500
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002501 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002502 {
Jamie Madill437fa652016-05-03 15:13:24 -04002503 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002504 return false;
2505 }
2506
2507 switch (pname)
2508 {
2509 case GL_QUERY_RESULT_EXT:
2510 case GL_QUERY_RESULT_AVAILABLE_EXT:
2511 break;
2512
2513 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002514 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002515 return false;
2516 }
2517
Geoff Lang2186c382016-10-14 10:54:54 -04002518 if (numParams)
2519 {
2520 *numParams = 1;
2521 }
2522
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002523 return true;
2524}
2525
2526bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2527{
2528 if (!context->getExtensions().disjointTimerQuery)
2529 {
Jamie Madill437fa652016-05-03 15:13:24 -04002530 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002531 return false;
2532 }
Geoff Lang2186c382016-10-14 10:54:54 -04002533 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2534}
2535
2536bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2537 GLuint id,
2538 GLenum pname,
2539 GLsizei bufSize,
2540 GLsizei *length,
2541 GLint *params)
2542{
2543 if (!context->getExtensions().disjointTimerQuery)
2544 {
2545 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2546 return false;
2547 }
2548
2549 if (!ValidateRobustEntryPoint(context, bufSize))
2550 {
2551 return false;
2552 }
2553
2554 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2555 {
2556 return false;
2557 }
2558
2559 if (!ValidateRobustBufferSize(context, bufSize, *length))
2560 {
2561 return false;
2562 }
2563
2564 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002565}
2566
2567bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2568{
2569 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002570 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002571 {
Jamie Madill437fa652016-05-03 15:13:24 -04002572 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002573 return false;
2574 }
Geoff Lang2186c382016-10-14 10:54:54 -04002575 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2576}
2577
2578bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2579 GLuint id,
2580 GLenum pname,
2581 GLsizei bufSize,
2582 GLsizei *length,
2583 GLuint *params)
2584{
2585 if (!context->getExtensions().disjointTimerQuery &&
2586 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2587 {
2588 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2589 return false;
2590 }
2591
2592 if (!ValidateRobustEntryPoint(context, bufSize))
2593 {
2594 return false;
2595 }
2596
2597 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2598 {
2599 return false;
2600 }
2601
2602 if (!ValidateRobustBufferSize(context, bufSize, *length))
2603 {
2604 return false;
2605 }
2606
2607 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002608}
2609
2610bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2611{
2612 if (!context->getExtensions().disjointTimerQuery)
2613 {
Jamie Madill437fa652016-05-03 15:13:24 -04002614 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002615 return false;
2616 }
Geoff Lang2186c382016-10-14 10:54:54 -04002617 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2618}
2619
2620bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2621 GLuint id,
2622 GLenum pname,
2623 GLsizei bufSize,
2624 GLsizei *length,
2625 GLint64 *params)
2626{
2627 if (!context->getExtensions().disjointTimerQuery)
2628 {
2629 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2630 return false;
2631 }
2632
2633 if (!ValidateRobustEntryPoint(context, bufSize))
2634 {
2635 return false;
2636 }
2637
2638 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2639 {
2640 return false;
2641 }
2642
2643 if (!ValidateRobustBufferSize(context, bufSize, *length))
2644 {
2645 return false;
2646 }
2647
2648 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002649}
2650
2651bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2652{
2653 if (!context->getExtensions().disjointTimerQuery)
2654 {
Jamie Madill437fa652016-05-03 15:13:24 -04002655 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002656 return false;
2657 }
Geoff Lang2186c382016-10-14 10:54:54 -04002658 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2659}
2660
2661bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2662 GLuint id,
2663 GLenum pname,
2664 GLsizei bufSize,
2665 GLsizei *length,
2666 GLuint64 *params)
2667{
2668 if (!context->getExtensions().disjointTimerQuery)
2669 {
2670 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2671 return false;
2672 }
2673
2674 if (!ValidateRobustEntryPoint(context, bufSize))
2675 {
2676 return false;
2677 }
2678
2679 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2680 {
2681 return false;
2682 }
2683
2684 if (!ValidateRobustBufferSize(context, bufSize, *length))
2685 {
2686 return false;
2687 }
2688
2689 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002690}
2691
Jamie Madill62d31cb2015-09-11 13:25:51 -04002692static bool ValidateUniformCommonBase(gl::Context *context,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002693 gl::Program *program,
Jamie Madill62d31cb2015-09-11 13:25:51 -04002694 GLenum targetUniformType,
2695 GLint location,
2696 GLsizei count,
2697 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002698{
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002699 // TODO(Jiajia): Add image uniform check in future.
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002700 if (count < 0)
2701 {
Jamie Madill437fa652016-05-03 15:13:24 -04002702 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002703 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002704 }
2705
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002706 if (!program || !program->isLinked())
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002707 {
Jamie Madill437fa652016-05-03 15:13:24 -04002708 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002709 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002710 }
2711
Jamie Madillac4e9c32017-01-13 14:07:12 -05002712 if (location == -1)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002713 {
2714 // Silently ignore the uniform command
2715 return false;
2716 }
2717
Jamie Madillac4e9c32017-01-13 14:07:12 -05002718 const auto &uniformLocations = program->getUniformLocations();
2719 size_t castedLocation = static_cast<size_t>(location);
2720 if (castedLocation >= uniformLocations.size())
2721 {
2722 context->handleError(Error(GL_INVALID_OPERATION, "Invalid uniform location"));
2723 return false;
2724 }
2725
2726 const auto &uniformLocation = uniformLocations[castedLocation];
2727 if (uniformLocation.ignored)
2728 {
2729 // Silently ignore the uniform command
2730 return false;
2731 }
2732
2733 if (!uniformLocation.used)
Jamie Madill36398922014-05-20 14:51:53 -04002734 {
Jamie Madill437fa652016-05-03 15:13:24 -04002735 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002736 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002737 }
2738
Jamie Madillac4e9c32017-01-13 14:07:12 -05002739 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
Jamie Madill36398922014-05-20 14:51:53 -04002740
2741 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002742 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002743 {
Jamie Madill437fa652016-05-03 15:13:24 -04002744 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002745 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002746 }
2747
Jamie Madill62d31cb2015-09-11 13:25:51 -04002748 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002749 return true;
2750}
2751
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002752bool ValidateProgramUniform(gl::Context *context,
2753 GLenum uniformType,
2754 GLuint program,
2755 GLint location,
2756 GLsizei count)
2757{
2758 // Check for ES31 program uniform entry points
2759 if (context->getClientVersion() < Version(3, 1))
2760 {
2761 context->handleError(Error(GL_INVALID_OPERATION));
2762 return false;
2763 }
2764
2765 const LinkedUniform *uniform = nullptr;
2766 gl::Program *programObject = GetValidProgram(context, program);
2767 if (!ValidateUniformCommonBase(context, programObject, uniformType, location, count, &uniform))
2768 {
2769 return false;
2770 }
2771
2772 GLenum targetBoolType = VariableBoolVectorType(uniformType);
2773 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
2774 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2775 {
2776 context->handleError(Error(GL_INVALID_OPERATION));
2777 return false;
2778 }
2779
2780 return true;
2781}
2782
2783bool ValidateProgramUniformMatrix(gl::Context *context,
2784 GLenum matrixType,
2785 GLuint program,
2786 GLint location,
2787 GLsizei count,
2788 GLboolean transpose)
2789{
2790 // Check for ES31 program uniform entry points
2791 if (context->getClientVersion() < Version(3, 1))
2792 {
2793 context->handleError(Error(GL_INVALID_OPERATION));
2794 return false;
2795 }
2796
2797 const LinkedUniform *uniform = nullptr;
2798 gl::Program *programObject = GetValidProgram(context, program);
2799 if (!ValidateUniformCommonBase(context, programObject, matrixType, location, count, &uniform))
2800 {
2801 return false;
2802 }
2803
2804 if (uniform->type != matrixType)
2805 {
2806 context->handleError(Error(GL_INVALID_OPERATION));
2807 return false;
2808 }
2809
2810 return true;
2811}
2812
Jamie Madillaa981bd2014-05-20 10:55:55 -04002813bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2814{
2815 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002816 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2817 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002818 {
Jamie Madill437fa652016-05-03 15:13:24 -04002819 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002820 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002821 }
2822
Jamie Madill62d31cb2015-09-11 13:25:51 -04002823 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002824 gl::Program *program = context->getGLState().getProgram();
2825 if (!ValidateUniformCommonBase(context, program, uniformType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002826 {
2827 return false;
2828 }
2829
He Yunchaoced53ae2016-11-29 15:00:51 +08002830 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002831 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002832 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2833 {
Jamie Madill437fa652016-05-03 15:13:24 -04002834 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002835 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002836 }
2837
2838 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002839}
2840
He Yunchaoced53ae2016-11-29 15:00:51 +08002841bool ValidateUniformMatrix(gl::Context *context,
2842 GLenum matrixType,
2843 GLint location,
2844 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002845 GLboolean transpose)
2846{
2847 // Check for ES3 uniform entry points
2848 int rows = VariableRowCount(matrixType);
2849 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002850 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002851 {
Jamie Madill437fa652016-05-03 15:13:24 -04002852 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002853 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002854 }
2855
Martin Radev1be913c2016-07-11 17:59:16 +03002856 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002857 {
Jamie Madill437fa652016-05-03 15:13:24 -04002858 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002859 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002860 }
2861
Jamie Madill62d31cb2015-09-11 13:25:51 -04002862 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002863 gl::Program *program = context->getGLState().getProgram();
2864 if (!ValidateUniformCommonBase(context, program, matrixType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002865 {
2866 return false;
2867 }
2868
2869 if (uniform->type != matrixType)
2870 {
Jamie Madill437fa652016-05-03 15:13:24 -04002871 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002872 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002873 }
2874
2875 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002876}
2877
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002878bool ValidateStateQuery(ValidationContext *context,
2879 GLenum pname,
2880 GLenum *nativeType,
2881 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002882{
2883 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2884 {
Jamie Madill437fa652016-05-03 15:13:24 -04002885 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002886 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002887 }
2888
Jamie Madill0af26e12015-03-05 19:54:33 -05002889 const Caps &caps = context->getCaps();
2890
Jamie Madill893ab082014-05-16 16:56:10 -04002891 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2892 {
2893 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2894
Jamie Madill0af26e12015-03-05 19:54:33 -05002895 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002896 {
Jamie Madill437fa652016-05-03 15:13:24 -04002897 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002898 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002899 }
2900 }
2901
2902 switch (pname)
2903 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002904 case GL_TEXTURE_BINDING_2D:
2905 case GL_TEXTURE_BINDING_CUBE_MAP:
2906 case GL_TEXTURE_BINDING_3D:
2907 case GL_TEXTURE_BINDING_2D_ARRAY:
2908 break;
2909 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2910 if (!context->getExtensions().eglStreamConsumerExternal &&
2911 !context->getExtensions().eglImageExternal)
2912 {
2913 context->handleError(Error(GL_INVALID_ENUM,
2914 "Neither NV_EGL_stream_consumer_external nor "
2915 "GL_OES_EGL_image_external extensions enabled"));
2916 return false;
2917 }
2918 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002919
He Yunchaoced53ae2016-11-29 15:00:51 +08002920 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2921 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002922 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002923 if (context->getGLState().getReadFramebuffer()->checkStatus(
2924 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002925 {
Jamie Madill437fa652016-05-03 15:13:24 -04002926 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002927 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002928 }
2929
Jamie Madill51f40ec2016-06-15 14:06:00 -04002930 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2931 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002932
2933 if (framebuffer->getReadBufferState() == GL_NONE)
2934 {
2935 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2936 return false;
2937 }
2938
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002939 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002940 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002941 {
Jamie Madill437fa652016-05-03 15:13:24 -04002942 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002943 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002944 }
2945 }
2946 break;
2947
He Yunchaoced53ae2016-11-29 15:00:51 +08002948 default:
2949 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002950 }
2951
2952 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002953 if (*numParams == 0)
2954 {
2955 return false;
2956 }
2957
2958 return true;
2959}
2960
2961bool ValidateRobustStateQuery(ValidationContext *context,
2962 GLenum pname,
2963 GLsizei bufSize,
2964 GLenum *nativeType,
2965 unsigned int *numParams)
2966{
2967 if (!ValidateRobustEntryPoint(context, bufSize))
2968 {
2969 return false;
2970 }
2971
2972 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2973 {
2974 return false;
2975 }
2976
2977 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002978 {
2979 return false;
2980 }
2981
2982 return true;
2983}
2984
Jamie Madillc29968b2016-01-20 11:17:23 -05002985bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2986 GLenum target,
2987 GLint level,
2988 GLenum internalformat,
2989 bool isSubImage,
2990 GLint xoffset,
2991 GLint yoffset,
2992 GLint zoffset,
2993 GLint x,
2994 GLint y,
2995 GLsizei width,
2996 GLsizei height,
2997 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002998 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002999{
Jamie Madill560a8d82014-05-21 13:06:20 -04003000 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
3001 {
Jamie Madill437fa652016-05-03 15:13:24 -04003002 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003003 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003004 }
3005
He Yunchaoced53ae2016-11-29 15:00:51 +08003006 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3007 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04003008 {
Jamie Madill437fa652016-05-03 15:13:24 -04003009 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003010 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003011 }
3012
3013 if (border != 0)
3014 {
Jamie Madill437fa652016-05-03 15:13:24 -04003015 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003016 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003017 }
3018
3019 if (!ValidMipLevel(context, target, level))
3020 {
Jamie Madill437fa652016-05-03 15:13:24 -04003021 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003022 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003023 }
3024
Jamie Madill51f40ec2016-06-15 14:06:00 -04003025 const auto &state = context->getGLState();
3026 auto readFramebuffer = state.getReadFramebuffer();
3027 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003028 {
Jamie Madill437fa652016-05-03 15:13:24 -04003029 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003030 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003031 }
3032
Jamie Madill51f40ec2016-06-15 14:06:00 -04003033 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003034 {
Jamie Madill437fa652016-05-03 15:13:24 -04003035 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003036 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003037 }
3038
Martin Radev138064f2016-07-15 12:03:41 +03003039 if (readFramebuffer->getReadBufferState() == GL_NONE)
3040 {
3041 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3042 return false;
3043 }
3044
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003045 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3046 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003047 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003048 // situation is an application error that would lead to a crash in ANGLE.
3049 if (readFramebuffer->getReadColorbuffer() == nullptr)
3050 {
3051 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3052 return false;
3053 }
3054
Geoff Langaae65a42014-05-26 12:43:44 -04003055 const gl::Caps &caps = context->getCaps();
3056
Geoff Langaae65a42014-05-26 12:43:44 -04003057 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003058 switch (target)
3059 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003060 case GL_TEXTURE_2D:
3061 maxDimension = caps.max2DTextureSize;
3062 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003063
He Yunchaoced53ae2016-11-29 15:00:51 +08003064 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3065 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3066 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3067 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3068 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3069 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3070 maxDimension = caps.maxCubeMapTextureSize;
3071 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003072
He Yunchaoced53ae2016-11-29 15:00:51 +08003073 case GL_TEXTURE_2D_ARRAY:
3074 maxDimension = caps.max2DTextureSize;
3075 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003076
He Yunchaoced53ae2016-11-29 15:00:51 +08003077 case GL_TEXTURE_3D:
3078 maxDimension = caps.max3DTextureSize;
3079 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003080
He Yunchaoced53ae2016-11-29 15:00:51 +08003081 default:
3082 context->handleError(Error(GL_INVALID_ENUM));
3083 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003084 }
3085
Jamie Madillc29968b2016-01-20 11:17:23 -05003086 gl::Texture *texture =
3087 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003088 if (!texture)
3089 {
Jamie Madill437fa652016-05-03 15:13:24 -04003090 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003091 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003092 }
3093
Geoff Lang69cce582015-09-17 13:20:36 -04003094 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003095 {
Jamie Madill437fa652016-05-03 15:13:24 -04003096 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003097 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003098 }
3099
Geoff Lang5d601382014-07-22 15:14:06 -04003100 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3101
3102 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003103 {
Jamie Madill437fa652016-05-03 15:13:24 -04003104 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003105 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003106 }
3107
Geoff Langa9be0dc2014-12-17 12:34:40 -05003108 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003109 {
Jamie Madill437fa652016-05-03 15:13:24 -04003110 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003111 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003112 }
3113
3114 if (isSubImage)
3115 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003116 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3117 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3118 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003119 {
Jamie Madill437fa652016-05-03 15:13:24 -04003120 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003121 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003122 }
3123 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003124 else
3125 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003126 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003127 {
Jamie Madill437fa652016-05-03 15:13:24 -04003128 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003129 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003130 }
3131
Geoff Langeb66a6e2016-10-31 13:06:12 -04003132 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003133 {
Jamie Madill437fa652016-05-03 15:13:24 -04003134 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003135 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003136 }
3137
3138 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003139 if (static_cast<int>(width) > maxLevelDimension ||
3140 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003141 {
Jamie Madill437fa652016-05-03 15:13:24 -04003142 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003143 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003144 }
3145 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003146
Jamie Madill0c8abca2016-07-22 20:21:26 -04003147 if (textureFormatOut)
3148 {
3149 *textureFormatOut = texture->getFormat(target, level);
3150 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003151
3152 // Detect texture copying feedback loops for WebGL.
3153 if (context->getExtensions().webglCompatibility)
3154 {
3155 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level))
3156 {
3157 context->handleError(Error(GL_INVALID_OPERATION,
3158 "Texture copying feedback loop formed between Framebuffer "
3159 "and specified Texture level."));
3160 return false;
3161 }
3162 }
3163
Jamie Madill560a8d82014-05-21 13:06:20 -04003164 return true;
3165}
3166
Jiajia Qind9671222016-11-29 16:30:31 +08003167bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003168{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003169 switch (mode)
3170 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003171 case GL_POINTS:
3172 case GL_LINES:
3173 case GL_LINE_LOOP:
3174 case GL_LINE_STRIP:
3175 case GL_TRIANGLES:
3176 case GL_TRIANGLE_STRIP:
3177 case GL_TRIANGLE_FAN:
3178 break;
3179 default:
3180 context->handleError(Error(GL_INVALID_ENUM));
3181 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003182 }
3183
Jamie Madill250d33f2014-06-06 17:09:03 -04003184 if (count < 0)
3185 {
Jamie Madill437fa652016-05-03 15:13:24 -04003186 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003187 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003188 }
3189
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003190 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003191
Jamie Madill250d33f2014-06-06 17:09:03 -04003192 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003193 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003194 {
Jamie Madill437fa652016-05-03 15:13:24 -04003195 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003196 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003197 }
3198
Jamie Madillcbcde722017-01-06 14:50:00 -05003199 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3200 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003201 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003202 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3203 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003204 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003205 const FramebufferAttachment *dsAttachment =
3206 framebuffer->getStencilOrDepthStencilAttachment();
3207 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003208 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003209 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003210
3211 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3212 bool differentWritemasks =
3213 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3214 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3215 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3216 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3217
3218 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003219 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003220 if (!context->getExtensions().webglCompatibility)
3221 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003222 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3223 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003224 }
Jamie Madill437fa652016-05-03 15:13:24 -04003225 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003226 return false;
3227 }
Jamie Madillac528012014-06-20 13:21:23 -04003228 }
3229
Jamie Madill51f40ec2016-06-15 14:06:00 -04003230 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003231 {
Jamie Madill437fa652016-05-03 15:13:24 -04003232 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003233 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003234 }
3235
Geoff Lang7dd2e102014-11-10 15:19:26 -05003236 gl::Program *program = state.getProgram();
3237 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003238 {
Jamie Madill437fa652016-05-03 15:13:24 -04003239 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003240 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003241 }
3242
Geoff Lang7dd2e102014-11-10 15:19:26 -05003243 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003244 {
Jamie Madill437fa652016-05-03 15:13:24 -04003245 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003246 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003247 }
3248
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003249 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003250 for (unsigned int uniformBlockIndex = 0;
3251 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003252 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003253 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003254 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003255 const OffsetBindingPointer<Buffer> &uniformBuffer =
3256 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003257
Geoff Lang5d124a62015-09-15 13:03:27 -04003258 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003259 {
3260 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003261 context->handleError(
3262 Error(GL_INVALID_OPERATION,
3263 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003264 return false;
3265 }
3266
Geoff Lang5d124a62015-09-15 13:03:27 -04003267 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003268 if (uniformBufferSize == 0)
3269 {
3270 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003271 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003272 }
3273
Jamie Madill62d31cb2015-09-11 13:25:51 -04003274 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003275 {
3276 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003277 context->handleError(
3278 Error(GL_INVALID_OPERATION,
3279 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003280 return false;
3281 }
3282 }
3283
Jamie Madilla4595b82017-01-11 17:36:34 -05003284 // Detect rendering feedback loops for WebGL.
3285 if (context->getExtensions().webglCompatibility)
3286 {
3287 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3288 {
3289 context->handleError(
3290 Error(GL_INVALID_OPERATION,
3291 "Rendering feedback loop formed between Framebuffer and active Texture."));
3292 return false;
3293 }
3294 }
3295
Jamie Madill250d33f2014-06-06 17:09:03 -04003296 // No-op if zero count
3297 return (count > 0);
3298}
3299
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003300bool ValidateDrawArrays(ValidationContext *context,
3301 GLenum mode,
3302 GLint first,
3303 GLsizei count,
3304 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003305{
Jamie Madillfd716582014-06-06 17:09:04 -04003306 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003307 {
Jamie Madill437fa652016-05-03 15:13:24 -04003308 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003309 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003310 }
3311
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003312 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003313 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003314 if (curTransformFeedback && curTransformFeedback->isActive() &&
3315 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003316 {
3317 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003318 // that does not match the current transform feedback object's draw mode (if transform
3319 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003320 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003321 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003322 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003323 }
3324
Jiajia Qind9671222016-11-29 16:30:31 +08003325 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003326 {
3327 return false;
3328 }
3329
Corentin Wallez71168a02016-12-19 15:11:18 -08003330 // Check the computation of maxVertex doesn't overflow.
3331 // - first < 0 or count < 0 have been checked as an error condition
3332 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3333 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3334 ASSERT(count > 0 && first >= 0);
3335 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3336 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003337 {
3338 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3339 return false;
3340 }
3341
Corentin Wallez71168a02016-12-19 15:11:18 -08003342 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003343 {
3344 return false;
3345 }
3346
3347 return true;
3348}
3349
He Yunchaoced53ae2016-11-29 15:00:51 +08003350bool ValidateDrawArraysInstanced(Context *context,
3351 GLenum mode,
3352 GLint first,
3353 GLsizei count,
3354 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003355{
3356 if (primcount < 0)
3357 {
Jamie Madill437fa652016-05-03 15:13:24 -04003358 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003359 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003360 }
3361
Jamie Madill2b976812014-08-25 15:47:49 -04003362 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003363 {
3364 return false;
3365 }
3366
3367 // No-op if zero primitive count
3368 return (primcount > 0);
3369}
3370
Geoff Lang87a93302014-09-16 13:29:43 -04003371static bool ValidateDrawInstancedANGLE(Context *context)
3372{
3373 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003374 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003375
Geoff Lang7dd2e102014-11-10 15:19:26 -05003376 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003377
3378 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003379 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003380 {
3381 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003382 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003383 {
3384 return true;
3385 }
3386 }
3387
Jamie Madill437fa652016-05-03 15:13:24 -04003388 context->handleError(Error(GL_INVALID_OPERATION,
3389 "ANGLE_instanced_arrays requires that at least one active attribute"
3390 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003391 return false;
3392}
3393
He Yunchaoced53ae2016-11-29 15:00:51 +08003394bool ValidateDrawArraysInstancedANGLE(Context *context,
3395 GLenum mode,
3396 GLint first,
3397 GLsizei count,
3398 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003399{
3400 if (!ValidateDrawInstancedANGLE(context))
3401 {
3402 return false;
3403 }
3404
3405 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3406}
3407
Jiajia Qind9671222016-11-29 16:30:31 +08003408bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003409{
Jamie Madill250d33f2014-06-06 17:09:03 -04003410 switch (type)
3411 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003412 case GL_UNSIGNED_BYTE:
3413 case GL_UNSIGNED_SHORT:
3414 break;
3415 case GL_UNSIGNED_INT:
3416 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3417 {
3418 context->handleError(Error(GL_INVALID_ENUM));
3419 return false;
3420 }
3421 break;
3422 default:
3423 context->handleError(Error(GL_INVALID_ENUM));
3424 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003425 }
3426
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003427 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003428
3429 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003430 if (curTransformFeedback && curTransformFeedback->isActive() &&
3431 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003432 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003433 // It is an invalid operation to call DrawElements, DrawRangeElements or
3434 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003435 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003436 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003437 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003438 }
3439
Jiajia Qind9671222016-11-29 16:30:31 +08003440 return true;
3441}
3442
3443bool ValidateDrawElements(ValidationContext *context,
3444 GLenum mode,
3445 GLsizei count,
3446 GLenum type,
3447 const GLvoid *indices,
3448 GLsizei primcount,
3449 IndexRange *indexRangeOut)
3450{
3451 if (!ValidateDrawElementsBase(context, type))
3452 return false;
3453
3454 const State &state = context->getGLState();
3455
Jamie Madill250d33f2014-06-06 17:09:03 -04003456 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003457 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003458 {
Jamie Madill437fa652016-05-03 15:13:24 -04003459 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003460 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003461 }
3462
He Yunchaoced53ae2016-11-29 15:00:51 +08003463 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003464 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003465
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003466 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3467
3468 if (context->getExtensions().webglCompatibility)
3469 {
3470 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3471 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3472 {
3473 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3474 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3475 // data type passed to the call, or an INVALID_OPERATION error is generated.
3476 context->handleError(Error(GL_INVALID_OPERATION,
3477 "indices must be a multiple of the element type size."));
3478 return false;
3479 }
3480 if (!elementArrayBuffer && count > 0)
3481 {
3482 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3483 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3484 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3485 context->handleError(Error(GL_INVALID_OPERATION,
3486 "There is no element array buffer bound and count > 0."));
3487 return false;
3488 }
3489 }
3490
Jamie Madillae3000b2014-08-25 15:47:51 -04003491 if (elementArrayBuffer)
3492 {
Jamie Madillae3000b2014-08-25 15:47:51 -04003493 GLint64 offset = reinterpret_cast<GLint64>(indices);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003494 GLint64 byteCount = static_cast<GLint64>(typeBytes) * static_cast<GLint64>(count) + offset;
Jamie Madillae3000b2014-08-25 15:47:51 -04003495
3496 // check for integer overflows
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003497 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeBytes) ||
Jamie Madillae3000b2014-08-25 15:47:51 -04003498 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3499 {
Jamie Madill437fa652016-05-03 15:13:24 -04003500 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003501 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003502 }
3503
3504 // Check for reading past the end of the bound buffer object
3505 if (byteCount > elementArrayBuffer->getSize())
3506 {
Jamie Madill437fa652016-05-03 15:13:24 -04003507 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003508 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003509 }
3510 }
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003511 else if (!indices && count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003512 {
Corentin Wallez327411e2016-12-09 11:09:17 -05003513 // This is an application error that would normally result in a crash,
3514 // but we catch it and return an error
3515 context->handleError(
3516 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003517 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003518 }
3519
Jiajia Qind9671222016-11-29 16:30:31 +08003520 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003521 {
3522 return false;
3523 }
3524
Jamie Madill2b976812014-08-25 15:47:49 -04003525 // Use max index to validate if our vertex buffers are large enough for the pull.
3526 // TODO: offer fast path, with disabled index validation.
3527 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3528 if (elementArrayBuffer)
3529 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003530 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003531 Error error =
3532 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3533 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003534 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003535 {
Jamie Madill437fa652016-05-03 15:13:24 -04003536 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003537 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003538 }
3539 }
3540 else
3541 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003542 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003543 }
3544
Jamie Madille79b1e12015-11-04 16:36:37 -05003545 // If we use an index greater than our maximum supported index range, return an error.
3546 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3547 // return an error if possible here.
3548 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3549 {
Jamie Madill437fa652016-05-03 15:13:24 -04003550 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003551 return false;
3552 }
3553
Corentin Wallez92db6942016-12-09 13:10:36 -05003554 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3555 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003556 {
3557 return false;
3558 }
3559
Geoff Lang3edfe032015-09-04 16:38:24 -04003560 // No op if there are no real indices in the index data (all are primitive restart).
3561 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003562}
3563
Geoff Langb1196682014-07-23 13:47:29 -04003564bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003565 GLenum mode,
3566 GLsizei count,
3567 GLenum type,
3568 const GLvoid *indices,
3569 GLsizei primcount,
3570 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003571{
3572 if (primcount < 0)
3573 {
Jamie Madill437fa652016-05-03 15:13:24 -04003574 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003575 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003576 }
3577
Jamie Madill2b976812014-08-25 15:47:49 -04003578 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003579 {
3580 return false;
3581 }
3582
3583 // No-op zero primitive count
3584 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003585}
3586
Geoff Lang3edfe032015-09-04 16:38:24 -04003587bool ValidateDrawElementsInstancedANGLE(Context *context,
3588 GLenum mode,
3589 GLsizei count,
3590 GLenum type,
3591 const GLvoid *indices,
3592 GLsizei primcount,
3593 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003594{
3595 if (!ValidateDrawInstancedANGLE(context))
3596 {
3597 return false;
3598 }
3599
He Yunchaoced53ae2016-11-29 15:00:51 +08003600 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3601 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003602}
3603
He Yunchaoced53ae2016-11-29 15:00:51 +08003604bool ValidateFramebufferTextureBase(Context *context,
3605 GLenum target,
3606 GLenum attachment,
3607 GLuint texture,
3608 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003609{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003610 if (!ValidFramebufferTarget(target))
3611 {
Jamie Madill437fa652016-05-03 15:13:24 -04003612 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003613 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003614 }
3615
3616 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003617 {
3618 return false;
3619 }
3620
Jamie Madill55ec3b12014-07-03 10:38:57 -04003621 if (texture != 0)
3622 {
3623 gl::Texture *tex = context->getTexture(texture);
3624
3625 if (tex == NULL)
3626 {
Jamie Madill437fa652016-05-03 15:13:24 -04003627 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003628 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003629 }
3630
3631 if (level < 0)
3632 {
Jamie Madill437fa652016-05-03 15:13:24 -04003633 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003634 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003635 }
3636 }
3637
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003638 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003639 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003640
Jamie Madill84115c92015-04-23 15:00:07 -04003641 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003642 {
Jamie Madill437fa652016-05-03 15:13:24 -04003643 context->handleError(
3644 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003645 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003646 }
3647
3648 return true;
3649}
3650
He Yunchaoced53ae2016-11-29 15:00:51 +08003651bool ValidateFramebufferTexture2D(Context *context,
3652 GLenum target,
3653 GLenum attachment,
3654 GLenum textarget,
3655 GLuint texture,
3656 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003657{
He Yunchaoced53ae2016-11-29 15:00:51 +08003658 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3659 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003660 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3661 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003662 {
Jamie Madill437fa652016-05-03 15:13:24 -04003663 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003664 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003665 }
3666
3667 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003668 {
3669 return false;
3670 }
3671
Jamie Madill55ec3b12014-07-03 10:38:57 -04003672 if (texture != 0)
3673 {
3674 gl::Texture *tex = context->getTexture(texture);
3675 ASSERT(tex);
3676
Jamie Madill2a6564e2014-07-11 09:53:19 -04003677 const gl::Caps &caps = context->getCaps();
3678
Jamie Madill55ec3b12014-07-03 10:38:57 -04003679 switch (textarget)
3680 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003681 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003682 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003683 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003684 {
Jamie Madill437fa652016-05-03 15:13:24 -04003685 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003686 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003687 }
3688 if (tex->getTarget() != GL_TEXTURE_2D)
3689 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003690 context->handleError(Error(GL_INVALID_OPERATION,
3691 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003692 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003693 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003694 }
3695 break;
3696
He Yunchaoced53ae2016-11-29 15:00:51 +08003697 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3698 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3699 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3700 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3701 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3702 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003703 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003704 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003705 {
Jamie Madill437fa652016-05-03 15:13:24 -04003706 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003707 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003708 }
3709 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3710 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003711 context->handleError(Error(GL_INVALID_OPERATION,
3712 "Textarget must match the texture target type."));
3713 return false;
3714 }
3715 }
3716 break;
3717
3718 case GL_TEXTURE_2D_MULTISAMPLE:
3719 {
3720 if (context->getClientVersion() < ES_3_1)
3721 {
3722 context->handleError(Error(GL_INVALID_OPERATION,
3723 "Texture target requires at least OpenGL ES 3.1."));
3724 return false;
3725 }
3726
3727 if (level != 0)
3728 {
3729 context->handleError(
3730 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
3731 return false;
3732 }
3733 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
3734 {
3735 context->handleError(Error(GL_INVALID_OPERATION,
3736 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003737 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003738 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003739 }
3740 break;
3741
He Yunchaoced53ae2016-11-29 15:00:51 +08003742 default:
3743 context->handleError(Error(GL_INVALID_ENUM));
3744 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003745 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003746
Jamie Madilla3944d42016-07-22 22:13:26 -04003747 const Format &format = tex->getFormat(textarget, level);
3748 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003749 {
Jamie Madill437fa652016-05-03 15:13:24 -04003750 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003751 return false;
3752 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003753 }
3754
Jamie Madill570f7c82014-07-03 10:38:54 -04003755 return true;
3756}
3757
Geoff Langb1196682014-07-23 13:47:29 -04003758bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003759{
3760 if (program == 0)
3761 {
Jamie Madill437fa652016-05-03 15:13:24 -04003762 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003763 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003764 }
3765
Dian Xiang769769a2015-09-09 15:20:08 -07003766 gl::Program *programObject = GetValidProgram(context, program);
3767 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003768 {
3769 return false;
3770 }
3771
Jamie Madill0063c512014-08-25 15:47:53 -04003772 if (!programObject || !programObject->isLinked())
3773 {
Jamie Madill437fa652016-05-03 15:13:24 -04003774 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003775 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003776 }
3777
Geoff Lang7dd2e102014-11-10 15:19:26 -05003778 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003779 {
Jamie Madill437fa652016-05-03 15:13:24 -04003780 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003781 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003782 }
3783
Jamie Madill0063c512014-08-25 15:47:53 -04003784 return true;
3785}
3786
He Yunchaoced53ae2016-11-29 15:00:51 +08003787bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003788{
3789 return ValidateGetUniformBase(context, program, location);
3790}
3791
He Yunchaoced53ae2016-11-29 15:00:51 +08003792bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003793{
Jamie Madill78f41802014-08-25 15:47:55 -04003794 return ValidateGetUniformBase(context, program, location);
3795}
3796
Geoff Langf41d0ee2016-10-07 13:04:23 -04003797static bool ValidateSizedGetUniform(Context *context,
3798 GLuint program,
3799 GLint location,
3800 GLsizei bufSize,
3801 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003802{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003803 if (length)
3804 {
3805 *length = 0;
3806 }
3807
Jamie Madill78f41802014-08-25 15:47:55 -04003808 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003809 {
Jamie Madill78f41802014-08-25 15:47:55 -04003810 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003811 }
3812
Geoff Langf41d0ee2016-10-07 13:04:23 -04003813 if (bufSize < 0)
3814 {
3815 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3816 return false;
3817 }
3818
Jamie Madilla502c742014-08-28 17:19:13 -04003819 gl::Program *programObject = context->getProgram(program);
3820 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003821
Jamie Madill78f41802014-08-25 15:47:55 -04003822 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003823 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003824 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003825 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003826 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003827 context->handleError(
3828 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003829 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003830 }
3831
Geoff Langf41d0ee2016-10-07 13:04:23 -04003832 if (length)
3833 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003834 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003835 }
3836
Jamie Madill0063c512014-08-25 15:47:53 -04003837 return true;
3838}
3839
He Yunchaoced53ae2016-11-29 15:00:51 +08003840bool ValidateGetnUniformfvEXT(Context *context,
3841 GLuint program,
3842 GLint location,
3843 GLsizei bufSize,
3844 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003845{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003846 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003847}
3848
He Yunchaoced53ae2016-11-29 15:00:51 +08003849bool ValidateGetnUniformivEXT(Context *context,
3850 GLuint program,
3851 GLint location,
3852 GLsizei bufSize,
3853 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003854{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003855 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3856}
3857
3858bool ValidateGetUniformfvRobustANGLE(Context *context,
3859 GLuint program,
3860 GLint location,
3861 GLsizei bufSize,
3862 GLsizei *length,
3863 GLfloat *params)
3864{
3865 if (!ValidateRobustEntryPoint(context, bufSize))
3866 {
3867 return false;
3868 }
3869
3870 // bufSize is validated in ValidateSizedGetUniform
3871 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3872}
3873
3874bool ValidateGetUniformivRobustANGLE(Context *context,
3875 GLuint program,
3876 GLint location,
3877 GLsizei bufSize,
3878 GLsizei *length,
3879 GLint *params)
3880{
3881 if (!ValidateRobustEntryPoint(context, bufSize))
3882 {
3883 return false;
3884 }
3885
3886 // bufSize is validated in ValidateSizedGetUniform
3887 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3888}
3889
3890bool ValidateGetUniformuivRobustANGLE(Context *context,
3891 GLuint program,
3892 GLint location,
3893 GLsizei bufSize,
3894 GLsizei *length,
3895 GLuint *params)
3896{
3897 if (!ValidateRobustEntryPoint(context, bufSize))
3898 {
3899 return false;
3900 }
3901
3902 if (context->getClientMajorVersion() < 3)
3903 {
3904 context->handleError(
3905 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3906 return false;
3907 }
3908
3909 // bufSize is validated in ValidateSizedGetUniform
3910 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003911}
3912
He Yunchaoced53ae2016-11-29 15:00:51 +08003913bool ValidateDiscardFramebufferBase(Context *context,
3914 GLenum target,
3915 GLsizei numAttachments,
3916 const GLenum *attachments,
3917 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003918{
3919 if (numAttachments < 0)
3920 {
Jamie Madill437fa652016-05-03 15:13:24 -04003921 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003922 return false;
3923 }
3924
3925 for (GLsizei i = 0; i < numAttachments; ++i)
3926 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003927 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003928 {
3929 if (defaultFramebuffer)
3930 {
Jamie Madill437fa652016-05-03 15:13:24 -04003931 context->handleError(Error(
3932 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003933 return false;
3934 }
3935
3936 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3937 {
Jamie Madill437fa652016-05-03 15:13:24 -04003938 context->handleError(Error(GL_INVALID_OPERATION,
3939 "Requested color attachment is greater than the maximum "
3940 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003941 return false;
3942 }
3943 }
3944 else
3945 {
3946 switch (attachments[i])
3947 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003948 case GL_DEPTH_ATTACHMENT:
3949 case GL_STENCIL_ATTACHMENT:
3950 case GL_DEPTH_STENCIL_ATTACHMENT:
3951 if (defaultFramebuffer)
3952 {
3953 context->handleError(
3954 Error(GL_INVALID_ENUM,
3955 "Invalid attachment when the default framebuffer is bound"));
3956 return false;
3957 }
3958 break;
3959 case GL_COLOR:
3960 case GL_DEPTH:
3961 case GL_STENCIL:
3962 if (!defaultFramebuffer)
3963 {
3964 context->handleError(
3965 Error(GL_INVALID_ENUM,
3966 "Invalid attachment when the default framebuffer is not bound"));
3967 return false;
3968 }
3969 break;
3970 default:
3971 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003972 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003973 }
3974 }
3975 }
3976
3977 return true;
3978}
3979
Austin Kinross6ee1e782015-05-29 17:05:37 -07003980bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3981{
3982 // Note that debug marker calls must not set error state
3983
3984 if (length < 0)
3985 {
3986 return false;
3987 }
3988
3989 if (marker == nullptr)
3990 {
3991 return false;
3992 }
3993
3994 return true;
3995}
3996
3997bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3998{
3999 // Note that debug marker calls must not set error state
4000
4001 if (length < 0)
4002 {
4003 return false;
4004 }
4005
4006 if (length > 0 && marker == nullptr)
4007 {
4008 return false;
4009 }
4010
4011 return true;
4012}
4013
Geoff Langdcab33b2015-07-21 13:03:16 -04004014bool ValidateEGLImageTargetTexture2DOES(Context *context,
4015 egl::Display *display,
4016 GLenum target,
4017 egl::Image *image)
4018{
Geoff Langa8406172015-07-21 16:53:39 -04004019 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4020 {
Jamie Madill437fa652016-05-03 15:13:24 -04004021 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004022 return false;
4023 }
4024
4025 switch (target)
4026 {
4027 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004028 if (!context->getExtensions().eglImage)
4029 {
4030 context->handleError(Error(
4031 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4032 }
4033 break;
4034
4035 case GL_TEXTURE_EXTERNAL_OES:
4036 if (!context->getExtensions().eglImageExternal)
4037 {
4038 context->handleError(Error(
4039 GL_INVALID_ENUM,
4040 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4041 }
Geoff Langa8406172015-07-21 16:53:39 -04004042 break;
4043
4044 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004045 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004046 return false;
4047 }
4048
4049 if (!display->isValidImage(image))
4050 {
Jamie Madill437fa652016-05-03 15:13:24 -04004051 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004052 return false;
4053 }
4054
4055 if (image->getSamples() > 0)
4056 {
Jamie Madill437fa652016-05-03 15:13:24 -04004057 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004058 "cannot create a 2D texture from a multisampled EGL image."));
4059 return false;
4060 }
4061
Jamie Madilla3944d42016-07-22 22:13:26 -04004062 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004063 if (!textureCaps.texturable)
4064 {
Jamie Madill437fa652016-05-03 15:13:24 -04004065 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004066 "EGL image internal format is not supported as a texture."));
4067 return false;
4068 }
4069
Geoff Langdcab33b2015-07-21 13:03:16 -04004070 return true;
4071}
4072
4073bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4074 egl::Display *display,
4075 GLenum target,
4076 egl::Image *image)
4077{
Geoff Langa8406172015-07-21 16:53:39 -04004078 if (!context->getExtensions().eglImage)
4079 {
Jamie Madill437fa652016-05-03 15:13:24 -04004080 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004081 return false;
4082 }
4083
4084 switch (target)
4085 {
4086 case GL_RENDERBUFFER:
4087 break;
4088
4089 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004090 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004091 return false;
4092 }
4093
4094 if (!display->isValidImage(image))
4095 {
Jamie Madill437fa652016-05-03 15:13:24 -04004096 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004097 return false;
4098 }
4099
Jamie Madilla3944d42016-07-22 22:13:26 -04004100 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004101 if (!textureCaps.renderable)
4102 {
Jamie Madill437fa652016-05-03 15:13:24 -04004103 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004104 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4105 return false;
4106 }
4107
Geoff Langdcab33b2015-07-21 13:03:16 -04004108 return true;
4109}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004110
4111bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4112{
Geoff Lang36167ab2015-12-07 10:27:14 -05004113 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004114 {
4115 // The default VAO should always exist
4116 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004117 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004118 return false;
4119 }
4120
4121 return true;
4122}
4123
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004124bool ValidateLinkProgram(Context *context, GLuint program)
4125{
4126 if (context->hasActiveTransformFeedback(program))
4127 {
4128 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004129 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004130 "Cannot link program while program is associated with an active "
4131 "transform feedback object."));
4132 return false;
4133 }
4134 return true;
4135}
4136
Geoff Langc5629752015-12-07 16:29:04 -05004137bool ValidateProgramBinaryBase(Context *context,
4138 GLuint program,
4139 GLenum binaryFormat,
4140 const void *binary,
4141 GLint length)
4142{
4143 Program *programObject = GetValidProgram(context, program);
4144 if (programObject == nullptr)
4145 {
4146 return false;
4147 }
4148
4149 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4150 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4151 programBinaryFormats.end())
4152 {
Jamie Madill437fa652016-05-03 15:13:24 -04004153 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004154 return false;
4155 }
4156
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004157 if (context->hasActiveTransformFeedback(program))
4158 {
4159 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004160 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004161 "Cannot change program binary while program is associated with "
4162 "an active transform feedback object."));
4163 return false;
4164 }
4165
Geoff Langc5629752015-12-07 16:29:04 -05004166 return true;
4167}
4168
4169bool ValidateGetProgramBinaryBase(Context *context,
4170 GLuint program,
4171 GLsizei bufSize,
4172 GLsizei *length,
4173 GLenum *binaryFormat,
4174 void *binary)
4175{
4176 Program *programObject = GetValidProgram(context, program);
4177 if (programObject == nullptr)
4178 {
4179 return false;
4180 }
4181
4182 if (!programObject->isLinked())
4183 {
Jamie Madill437fa652016-05-03 15:13:24 -04004184 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004185 return false;
4186 }
4187
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004188 if (context->getCaps().programBinaryFormats.empty())
4189 {
4190 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4191 return false;
4192 }
4193
Geoff Langc5629752015-12-07 16:29:04 -05004194 return true;
4195}
Jamie Madillc29968b2016-01-20 11:17:23 -05004196
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004197bool ValidateUseProgram(Context *context, GLuint program)
4198{
4199 if (program != 0)
4200 {
4201 Program *programObject = context->getProgram(program);
4202 if (!programObject)
4203 {
4204 // ES 3.1.0 section 7.3 page 72
4205 if (context->getShader(program))
4206 {
Jamie Madill437fa652016-05-03 15:13:24 -04004207 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004208 Error(GL_INVALID_OPERATION,
4209 "Attempted to use a single shader instead of a shader program."));
4210 return false;
4211 }
4212 else
4213 {
Jamie Madill437fa652016-05-03 15:13:24 -04004214 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004215 return false;
4216 }
4217 }
4218 if (!programObject->isLinked())
4219 {
Jamie Madill437fa652016-05-03 15:13:24 -04004220 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004221 return false;
4222 }
4223 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004224 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004225 {
4226 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004227 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004228 Error(GL_INVALID_OPERATION,
4229 "Cannot change active program while transform feedback is unpaused."));
4230 return false;
4231 }
4232
4233 return true;
4234}
4235
Jamie Madillc29968b2016-01-20 11:17:23 -05004236bool ValidateCopyTexImage2D(ValidationContext *context,
4237 GLenum target,
4238 GLint level,
4239 GLenum internalformat,
4240 GLint x,
4241 GLint y,
4242 GLsizei width,
4243 GLsizei height,
4244 GLint border)
4245{
Martin Radev1be913c2016-07-11 17:59:16 +03004246 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004247 {
4248 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4249 0, x, y, width, height, border);
4250 }
4251
Martin Radev1be913c2016-07-11 17:59:16 +03004252 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004253 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4254 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004255}
Jamie Madillc29968b2016-01-20 11:17:23 -05004256
4257bool ValidateFramebufferRenderbuffer(Context *context,
4258 GLenum target,
4259 GLenum attachment,
4260 GLenum renderbuffertarget,
4261 GLuint renderbuffer)
4262{
4263 if (!ValidFramebufferTarget(target) ||
4264 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4265 {
Jamie Madill437fa652016-05-03 15:13:24 -04004266 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004267 return false;
4268 }
4269
4270 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4271 renderbuffertarget, renderbuffer);
4272}
4273
4274bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4275{
4276 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4277 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4278 {
Jamie Madill437fa652016-05-03 15:13:24 -04004279 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004280 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4281 return false;
4282 }
4283
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004284 ASSERT(context->getGLState().getDrawFramebuffer());
4285 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004286 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4287
4288 // This should come first before the check for the default frame buffer
4289 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4290 // rather than INVALID_OPERATION
4291 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4292 {
4293 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4294
4295 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004296 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4297 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004298 {
4299 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004300 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4301 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4302 // 3.1 is still a bit ambiguous about the error, but future specs are
4303 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004304 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004305 return false;
4306 }
4307 else if (bufs[colorAttachment] >= maxColorAttachment)
4308 {
Jamie Madill437fa652016-05-03 15:13:24 -04004309 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004310 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004311 return false;
4312 }
4313 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4314 frameBufferId != 0)
4315 {
4316 // INVALID_OPERATION-GL is bound to buffer and ith argument
4317 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004318 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004319 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4320 return false;
4321 }
4322 }
4323
4324 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4325 // and n is not 1 or bufs is bound to value other than BACK and NONE
4326 if (frameBufferId == 0)
4327 {
4328 if (n != 1)
4329 {
Jamie Madill437fa652016-05-03 15:13:24 -04004330 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004331 "n must be 1 when GL is bound to the default framebuffer"));
4332 return false;
4333 }
4334
4335 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4336 {
Jamie Madill437fa652016-05-03 15:13:24 -04004337 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004338 GL_INVALID_OPERATION,
4339 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4340 return false;
4341 }
4342 }
4343
4344 return true;
4345}
4346
4347bool ValidateCopyTexSubImage2D(Context *context,
4348 GLenum target,
4349 GLint level,
4350 GLint xoffset,
4351 GLint yoffset,
4352 GLint x,
4353 GLint y,
4354 GLsizei width,
4355 GLsizei height)
4356{
Martin Radev1be913c2016-07-11 17:59:16 +03004357 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004358 {
4359 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4360 yoffset, x, y, width, height, 0);
4361 }
4362
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004363 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4364 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004365}
4366
Geoff Lang496c02d2016-10-20 11:38:11 -07004367bool ValidateGetBufferPointervBase(Context *context,
4368 GLenum target,
4369 GLenum pname,
4370 GLsizei *length,
4371 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004372{
Geoff Lang496c02d2016-10-20 11:38:11 -07004373 if (length)
4374 {
4375 *length = 0;
4376 }
4377
4378 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4379 {
4380 context->handleError(
4381 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004382 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004383 return false;
4384 }
4385
Olli Etuaho4f667482016-03-30 15:56:35 +03004386 if (!ValidBufferTarget(context, target))
4387 {
Jamie Madill437fa652016-05-03 15:13:24 -04004388 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004389 return false;
4390 }
4391
Geoff Lang496c02d2016-10-20 11:38:11 -07004392 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004393 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004394 case GL_BUFFER_MAP_POINTER:
4395 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004396
Geoff Lang496c02d2016-10-20 11:38:11 -07004397 default:
4398 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4399 return false;
4400 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004401
4402 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4403 // target bound to zero generate an INVALID_OPERATION error."
4404 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004405 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004406 {
Jamie Madill437fa652016-05-03 15:13:24 -04004407 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004408 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4409 return false;
4410 }
4411
Geoff Lang496c02d2016-10-20 11:38:11 -07004412 if (length)
4413 {
4414 *length = 1;
4415 }
4416
Olli Etuaho4f667482016-03-30 15:56:35 +03004417 return true;
4418}
4419
4420bool ValidateUnmapBufferBase(Context *context, GLenum target)
4421{
4422 if (!ValidBufferTarget(context, target))
4423 {
Jamie Madill437fa652016-05-03 15:13:24 -04004424 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004425 return false;
4426 }
4427
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004428 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004429
4430 if (buffer == nullptr || !buffer->isMapped())
4431 {
Jamie Madill437fa652016-05-03 15:13:24 -04004432 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004433 return false;
4434 }
4435
4436 return true;
4437}
4438
4439bool ValidateMapBufferRangeBase(Context *context,
4440 GLenum target,
4441 GLintptr offset,
4442 GLsizeiptr length,
4443 GLbitfield access)
4444{
4445 if (!ValidBufferTarget(context, target))
4446 {
Jamie Madill437fa652016-05-03 15:13:24 -04004447 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004448 return false;
4449 }
4450
4451 if (offset < 0 || length < 0)
4452 {
Jamie Madill437fa652016-05-03 15:13:24 -04004453 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004454 return false;
4455 }
4456
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004457 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004458
4459 if (!buffer)
4460 {
Jamie Madill437fa652016-05-03 15:13:24 -04004461 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004462 return false;
4463 }
4464
4465 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004466 CheckedNumeric<size_t> checkedOffset(offset);
4467 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004468
Jamie Madille2e406c2016-06-02 13:04:10 -04004469 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004470 {
Jamie Madill437fa652016-05-03 15:13:24 -04004471 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004472 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4473 return false;
4474 }
4475
4476 // Check for invalid bits in the mask
4477 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4478 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4479 GL_MAP_UNSYNCHRONIZED_BIT;
4480
4481 if (access & ~(allAccessBits))
4482 {
Jamie Madill437fa652016-05-03 15:13:24 -04004483 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004484 return false;
4485 }
4486
4487 if (length == 0)
4488 {
Jamie Madill437fa652016-05-03 15:13:24 -04004489 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004490 return false;
4491 }
4492
4493 if (buffer->isMapped())
4494 {
Jamie Madill437fa652016-05-03 15:13:24 -04004495 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004496 return false;
4497 }
4498
4499 // Check for invalid bit combinations
4500 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4501 {
Jamie Madill437fa652016-05-03 15:13:24 -04004502 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004503 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4504 return false;
4505 }
4506
4507 GLbitfield writeOnlyBits =
4508 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4509
4510 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4511 {
Jamie Madill437fa652016-05-03 15:13:24 -04004512 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004513 "Invalid access bits when mapping buffer for reading: 0x%X.",
4514 access));
4515 return false;
4516 }
4517
4518 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4519 {
Jamie Madill437fa652016-05-03 15:13:24 -04004520 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004521 GL_INVALID_OPERATION,
4522 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4523 return false;
4524 }
4525 return true;
4526}
4527
4528bool ValidateFlushMappedBufferRangeBase(Context *context,
4529 GLenum target,
4530 GLintptr offset,
4531 GLsizeiptr length)
4532{
4533 if (offset < 0 || length < 0)
4534 {
Jamie Madill437fa652016-05-03 15:13:24 -04004535 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004536 return false;
4537 }
4538
4539 if (!ValidBufferTarget(context, target))
4540 {
Jamie Madill437fa652016-05-03 15:13:24 -04004541 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004542 return false;
4543 }
4544
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004545 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004546
4547 if (buffer == nullptr)
4548 {
Jamie Madill437fa652016-05-03 15:13:24 -04004549 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004550 return false;
4551 }
4552
4553 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4554 {
Jamie Madill437fa652016-05-03 15:13:24 -04004555 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004556 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4557 return false;
4558 }
4559
4560 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004561 CheckedNumeric<size_t> checkedOffset(offset);
4562 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004563
Jamie Madille2e406c2016-06-02 13:04:10 -04004564 if (!checkedSize.IsValid() ||
4565 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004566 {
Jamie Madill437fa652016-05-03 15:13:24 -04004567 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004568 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4569 return false;
4570 }
4571
4572 return true;
4573}
4574
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004575bool ValidateGenerateMipmap(Context *context, GLenum target)
4576{
4577 if (!ValidTextureTarget(context, target))
4578 {
4579 context->handleError(Error(GL_INVALID_ENUM));
4580 return false;
4581 }
4582
4583 Texture *texture = context->getTargetTexture(target);
4584
4585 if (texture == nullptr)
4586 {
4587 context->handleError(Error(GL_INVALID_OPERATION));
4588 return false;
4589 }
4590
4591 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4592
4593 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4594 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4595 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4596 {
4597 context->handleError(Error(GL_INVALID_OPERATION));
4598 return false;
4599 }
4600
Jamie Madilla3944d42016-07-22 22:13:26 -04004601 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4602 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4603 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004604
4605 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4606 // unsized formats or that are color renderable and filterable. Since we do not track if
4607 // the texture was created with sized or unsized format (only sized formats are stored),
4608 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4609 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4610 // textures since they're the only texture format that can be created with unsized formats
4611 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4612 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004613 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4614 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004615 {
4616 context->handleError(Error(GL_INVALID_OPERATION));
4617 return false;
4618 }
4619
4620 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004621 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004622 {
4623 context->handleError(Error(GL_INVALID_OPERATION));
4624 return false;
4625 }
4626
4627 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004628 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004629 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4630 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4631 {
Geoff Lang55482a12016-11-21 16:54:01 -05004632 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004633 context->handleError(Error(GL_INVALID_OPERATION));
4634 return false;
4635 }
4636
4637 // Cube completeness check
4638 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4639 {
4640 context->handleError(Error(GL_INVALID_OPERATION));
4641 return false;
4642 }
4643
4644 return true;
4645}
4646
Olli Etuaho41997e72016-03-10 13:38:39 +02004647bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4648{
4649 return ValidateGenOrDelete(context, n);
4650}
4651
4652bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4653{
4654 return ValidateGenOrDelete(context, n);
4655}
4656
4657bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4658{
4659 return ValidateGenOrDelete(context, n);
4660}
4661
4662bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4663{
4664 return ValidateGenOrDelete(context, n);
4665}
4666
4667bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4668{
4669 return ValidateGenOrDelete(context, n);
4670}
4671
4672bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4673{
4674 return ValidateGenOrDelete(context, n);
4675}
4676
4677bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4678{
4679 return ValidateGenOrDelete(context, n);
4680}
4681
4682bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4683{
4684 return ValidateGenOrDelete(context, n);
4685}
4686
4687bool ValidateGenOrDelete(Context *context, GLint n)
4688{
4689 if (n < 0)
4690 {
Jamie Madill437fa652016-05-03 15:13:24 -04004691 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004692 return false;
4693 }
4694 return true;
4695}
4696
Geoff Langf41a7152016-09-19 15:11:17 -04004697bool ValidateEnable(Context *context, GLenum cap)
4698{
4699 if (!ValidCap(context, cap, false))
4700 {
4701 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4702 return false;
4703 }
4704
4705 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4706 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4707 {
4708 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4709 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4710
4711 // We also output an error message to the debugger window if tracing is active, so that
4712 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05004713 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04004714 return false;
4715 }
4716
4717 return true;
4718}
4719
4720bool ValidateDisable(Context *context, GLenum cap)
4721{
4722 if (!ValidCap(context, cap, false))
4723 {
4724 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4725 return false;
4726 }
4727
4728 return true;
4729}
4730
4731bool ValidateIsEnabled(Context *context, GLenum cap)
4732{
4733 if (!ValidCap(context, cap, true))
4734 {
4735 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4736 return false;
4737 }
4738
4739 return true;
4740}
4741
Geoff Langff5b2d52016-09-07 11:32:23 -04004742bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4743{
4744 if (!context->getExtensions().robustClientMemory)
4745 {
4746 context->handleError(
4747 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4748 return false;
4749 }
4750
4751 if (bufSize < 0)
4752 {
4753 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4754 return false;
4755 }
4756
4757 return true;
4758}
4759
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004760bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4761{
4762 if (bufSize < numParams)
4763 {
4764 context->handleError(Error(GL_INVALID_OPERATION,
4765 "%u parameters are required but %i were provided.", numParams,
4766 bufSize));
4767 return false;
4768 }
4769
4770 return true;
4771}
4772
Geoff Langff5b2d52016-09-07 11:32:23 -04004773bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4774 GLenum target,
4775 GLenum attachment,
4776 GLenum pname,
4777 GLsizei *numParams)
4778{
4779 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4780 *numParams = 1;
4781
4782 if (!ValidFramebufferTarget(target))
4783 {
4784 context->handleError(Error(GL_INVALID_ENUM));
4785 return false;
4786 }
4787
4788 int clientVersion = context->getClientMajorVersion();
4789
4790 switch (pname)
4791 {
4792 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4793 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4794 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4795 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4796 break;
4797
4798 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4799 if (clientVersion < 3 && !context->getExtensions().sRGB)
4800 {
4801 context->handleError(Error(GL_INVALID_ENUM));
4802 return false;
4803 }
4804 break;
4805
4806 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4807 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4808 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4809 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4810 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4811 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4812 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4813 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4814 if (clientVersion < 3)
4815 {
4816 context->handleError(Error(GL_INVALID_ENUM));
4817 return false;
4818 }
4819 break;
4820
4821 default:
4822 context->handleError(Error(GL_INVALID_ENUM));
4823 return false;
4824 }
4825
4826 // Determine if the attachment is a valid enum
4827 switch (attachment)
4828 {
4829 case GL_BACK:
4830 case GL_FRONT:
4831 case GL_DEPTH:
4832 case GL_STENCIL:
4833 case GL_DEPTH_STENCIL_ATTACHMENT:
4834 if (clientVersion < 3)
4835 {
4836 context->handleError(Error(GL_INVALID_ENUM));
4837 return false;
4838 }
4839 break;
4840
4841 case GL_DEPTH_ATTACHMENT:
4842 case GL_STENCIL_ATTACHMENT:
4843 break;
4844
4845 default:
4846 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4847 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4848 {
4849 context->handleError(Error(GL_INVALID_ENUM));
4850 return false;
4851 }
4852 break;
4853 }
4854
4855 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4856 ASSERT(framebuffer);
4857
4858 if (framebuffer->id() == 0)
4859 {
4860 if (clientVersion < 3)
4861 {
4862 context->handleError(Error(GL_INVALID_OPERATION));
4863 return false;
4864 }
4865
4866 switch (attachment)
4867 {
4868 case GL_BACK:
4869 case GL_DEPTH:
4870 case GL_STENCIL:
4871 break;
4872
4873 default:
4874 context->handleError(Error(GL_INVALID_OPERATION));
4875 return false;
4876 }
4877 }
4878 else
4879 {
4880 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4881 {
4882 // Valid attachment query
4883 }
4884 else
4885 {
4886 switch (attachment)
4887 {
4888 case GL_DEPTH_ATTACHMENT:
4889 case GL_STENCIL_ATTACHMENT:
4890 break;
4891
4892 case GL_DEPTH_STENCIL_ATTACHMENT:
4893 if (!framebuffer->hasValidDepthStencil())
4894 {
4895 context->handleError(Error(GL_INVALID_OPERATION));
4896 return false;
4897 }
4898 break;
4899
4900 default:
4901 context->handleError(Error(GL_INVALID_OPERATION));
4902 return false;
4903 }
4904 }
4905 }
4906
4907 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4908 if (attachmentObject)
4909 {
4910 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4911 attachmentObject->type() == GL_TEXTURE ||
4912 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4913
4914 switch (pname)
4915 {
4916 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4917 if (attachmentObject->type() != GL_RENDERBUFFER &&
4918 attachmentObject->type() != GL_TEXTURE)
4919 {
4920 context->handleError(Error(GL_INVALID_ENUM));
4921 return false;
4922 }
4923 break;
4924
4925 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4926 if (attachmentObject->type() != GL_TEXTURE)
4927 {
4928 context->handleError(Error(GL_INVALID_ENUM));
4929 return false;
4930 }
4931 break;
4932
4933 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4934 if (attachmentObject->type() != GL_TEXTURE)
4935 {
4936 context->handleError(Error(GL_INVALID_ENUM));
4937 return false;
4938 }
4939 break;
4940
4941 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4942 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4943 {
4944 context->handleError(Error(GL_INVALID_OPERATION));
4945 return false;
4946 }
4947 break;
4948
4949 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4950 if (attachmentObject->type() != GL_TEXTURE)
4951 {
4952 context->handleError(Error(GL_INVALID_ENUM));
4953 return false;
4954 }
4955 break;
4956
4957 default:
4958 break;
4959 }
4960 }
4961 else
4962 {
4963 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4964 // is NONE, then querying any other pname will generate INVALID_ENUM.
4965
4966 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4967 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4968 // INVALID_OPERATION for all other pnames
4969
4970 switch (pname)
4971 {
4972 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4973 break;
4974
4975 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4976 if (clientVersion < 3)
4977 {
4978 context->handleError(Error(GL_INVALID_ENUM));
4979 return false;
4980 }
4981 break;
4982
4983 default:
4984 if (clientVersion < 3)
4985 {
4986 context->handleError(Error(GL_INVALID_ENUM));
4987 return false;
4988 }
4989 else
4990 {
4991 context->handleError(Error(GL_INVALID_OPERATION));
4992 return false;
4993 }
4994 }
4995 }
4996
4997 return true;
4998}
4999
5000bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5001 GLenum target,
5002 GLenum attachment,
5003 GLenum pname,
5004 GLsizei bufSize,
5005 GLsizei *numParams)
5006{
5007 if (!ValidateRobustEntryPoint(context, bufSize))
5008 {
5009 return false;
5010 }
5011
5012 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5013 {
5014 return false;
5015 }
5016
5017 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5018 {
5019 return false;
5020 }
5021
5022 return true;
5023}
5024
5025bool ValidateGetBufferParameteriv(ValidationContext *context,
5026 GLenum target,
5027 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005028 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005029{
Geoff Langebebe1c2016-10-14 12:01:31 -04005030 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005031}
5032
5033bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5034 GLenum target,
5035 GLenum pname,
5036 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005037 GLsizei *length,
5038 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005039{
5040 if (!ValidateRobustEntryPoint(context, bufSize))
5041 {
5042 return false;
5043 }
5044
Geoff Langebebe1c2016-10-14 12:01:31 -04005045 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005046 {
5047 return false;
5048 }
5049
Geoff Langebebe1c2016-10-14 12:01:31 -04005050 if (!ValidateRobustBufferSize(context, bufSize, *length))
5051 {
5052 return false;
5053 }
5054
5055 return true;
5056}
5057
5058bool ValidateGetBufferParameteri64v(ValidationContext *context,
5059 GLenum target,
5060 GLenum pname,
5061 GLint64 *params)
5062{
5063 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5064}
5065
5066bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5067 GLenum target,
5068 GLenum pname,
5069 GLsizei bufSize,
5070 GLsizei *length,
5071 GLint64 *params)
5072{
5073 if (!ValidateRobustEntryPoint(context, bufSize))
5074 {
5075 return false;
5076 }
5077
5078 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5079 {
5080 return false;
5081 }
5082
5083 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005084 {
5085 return false;
5086 }
5087
5088 return true;
5089}
5090
5091bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5092{
5093 // Currently, all GetProgramiv queries return 1 parameter
5094 *numParams = 1;
5095
5096 Program *programObject = GetValidProgram(context, program);
5097 if (!programObject)
5098 {
5099 return false;
5100 }
5101
5102 switch (pname)
5103 {
5104 case GL_DELETE_STATUS:
5105 case GL_LINK_STATUS:
5106 case GL_VALIDATE_STATUS:
5107 case GL_INFO_LOG_LENGTH:
5108 case GL_ATTACHED_SHADERS:
5109 case GL_ACTIVE_ATTRIBUTES:
5110 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5111 case GL_ACTIVE_UNIFORMS:
5112 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5113 break;
5114
5115 case GL_PROGRAM_BINARY_LENGTH:
5116 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5117 {
5118 context->handleError(Error(GL_INVALID_ENUM,
5119 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5120 "GL_OES_get_program_binary or ES 3.0."));
5121 return false;
5122 }
5123 break;
5124
5125 case GL_ACTIVE_UNIFORM_BLOCKS:
5126 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5127 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5128 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5129 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5130 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5131 if (context->getClientMajorVersion() < 3)
5132 {
5133 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5134 return false;
5135 }
5136 break;
5137
5138 default:
5139 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5140 return false;
5141 }
5142
5143 return true;
5144}
5145
5146bool ValidateGetProgramivRobustANGLE(Context *context,
5147 GLuint program,
5148 GLenum pname,
5149 GLsizei bufSize,
5150 GLsizei *numParams)
5151{
5152 if (!ValidateRobustEntryPoint(context, bufSize))
5153 {
5154 return false;
5155 }
5156
5157 if (!ValidateGetProgramiv(context, program, pname, numParams))
5158 {
5159 return false;
5160 }
5161
5162 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5163 {
5164 return false;
5165 }
5166
5167 return true;
5168}
5169
Geoff Lang740d9022016-10-07 11:20:52 -04005170bool ValidateGetRenderbufferParameteriv(Context *context,
5171 GLenum target,
5172 GLenum pname,
5173 GLint *params)
5174{
5175 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5176}
5177
5178bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5179 GLenum target,
5180 GLenum pname,
5181 GLsizei bufSize,
5182 GLsizei *length,
5183 GLint *params)
5184{
5185 if (!ValidateRobustEntryPoint(context, bufSize))
5186 {
5187 return false;
5188 }
5189
5190 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5191 {
5192 return false;
5193 }
5194
5195 if (!ValidateRobustBufferSize(context, bufSize, *length))
5196 {
5197 return false;
5198 }
5199
5200 return true;
5201}
5202
Geoff Langd7d0ed32016-10-07 11:33:51 -04005203bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5204{
5205 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5206}
5207
5208bool ValidateGetShaderivRobustANGLE(Context *context,
5209 GLuint shader,
5210 GLenum pname,
5211 GLsizei bufSize,
5212 GLsizei *length,
5213 GLint *params)
5214{
5215 if (!ValidateRobustEntryPoint(context, bufSize))
5216 {
5217 return false;
5218 }
5219
5220 if (!ValidateGetShaderivBase(context, shader, pname, length))
5221 {
5222 return false;
5223 }
5224
5225 if (!ValidateRobustBufferSize(context, bufSize, *length))
5226 {
5227 return false;
5228 }
5229
5230 return true;
5231}
5232
Geoff Langc1984ed2016-10-07 12:41:00 -04005233bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5234{
5235 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5236}
5237
5238bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5239 GLenum target,
5240 GLenum pname,
5241 GLsizei bufSize,
5242 GLsizei *length,
5243 GLfloat *params)
5244{
5245 if (!ValidateRobustEntryPoint(context, bufSize))
5246 {
5247 return false;
5248 }
5249
5250 if (!ValidateGetTexParameterBase(context, target, pname, length))
5251 {
5252 return false;
5253 }
5254
5255 if (!ValidateRobustBufferSize(context, bufSize, *length))
5256 {
5257 return false;
5258 }
5259
5260 return true;
5261}
5262
5263bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5264{
5265 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5266}
5267
5268bool ValidateGetTexParameterivRobustANGLE(Context *context,
5269 GLenum target,
5270 GLenum pname,
5271 GLsizei bufSize,
5272 GLsizei *length,
5273 GLint *params)
5274{
5275 if (!ValidateRobustEntryPoint(context, bufSize))
5276 {
5277 return false;
5278 }
5279
5280 if (!ValidateGetTexParameterBase(context, target, pname, length))
5281 {
5282 return false;
5283 }
5284
5285 if (!ValidateRobustBufferSize(context, bufSize, *length))
5286 {
5287 return false;
5288 }
5289
5290 return true;
5291}
5292
5293bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5294{
5295 return ValidateTexParameterBase(context, target, pname, -1, &param);
5296}
5297
5298bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5299{
5300 return ValidateTexParameterBase(context, target, pname, -1, params);
5301}
5302
5303bool ValidateTexParameterfvRobustANGLE(Context *context,
5304 GLenum target,
5305 GLenum pname,
5306 GLsizei bufSize,
5307 const GLfloat *params)
5308{
5309 if (!ValidateRobustEntryPoint(context, bufSize))
5310 {
5311 return false;
5312 }
5313
5314 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5315}
5316
5317bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5318{
5319 return ValidateTexParameterBase(context, target, pname, -1, &param);
5320}
5321
5322bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5323{
5324 return ValidateTexParameterBase(context, target, pname, -1, params);
5325}
5326
5327bool ValidateTexParameterivRobustANGLE(Context *context,
5328 GLenum target,
5329 GLenum pname,
5330 GLsizei bufSize,
5331 const GLint *params)
5332{
5333 if (!ValidateRobustEntryPoint(context, bufSize))
5334 {
5335 return false;
5336 }
5337
5338 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5339}
5340
5341bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5342{
5343 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5344}
5345
5346bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5347 GLuint sampler,
5348 GLenum pname,
5349 GLuint bufSize,
5350 GLsizei *length,
5351 GLfloat *params)
5352{
5353 if (!ValidateRobustEntryPoint(context, bufSize))
5354 {
5355 return false;
5356 }
5357
5358 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5359 {
5360 return false;
5361 }
5362
5363 if (!ValidateRobustBufferSize(context, bufSize, *length))
5364 {
5365 return false;
5366 }
5367
5368 return true;
5369}
5370
5371bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5372{
5373 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5374}
5375
5376bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5377 GLuint sampler,
5378 GLenum pname,
5379 GLuint bufSize,
5380 GLsizei *length,
5381 GLint *params)
5382{
5383 if (!ValidateRobustEntryPoint(context, bufSize))
5384 {
5385 return false;
5386 }
5387
5388 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5389 {
5390 return false;
5391 }
5392
5393 if (!ValidateRobustBufferSize(context, bufSize, *length))
5394 {
5395 return false;
5396 }
5397
5398 return true;
5399}
5400
5401bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5402{
5403 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5404}
5405
5406bool ValidateSamplerParameterfv(Context *context,
5407 GLuint sampler,
5408 GLenum pname,
5409 const GLfloat *params)
5410{
5411 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5412}
5413
5414bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5415 GLuint sampler,
5416 GLenum pname,
5417 GLsizei bufSize,
5418 const GLfloat *params)
5419{
5420 if (!ValidateRobustEntryPoint(context, bufSize))
5421 {
5422 return false;
5423 }
5424
5425 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5426}
5427
5428bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5429{
5430 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5431}
5432
5433bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5434{
5435 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5436}
5437
5438bool ValidateSamplerParameterivRobustANGLE(Context *context,
5439 GLuint sampler,
5440 GLenum pname,
5441 GLsizei bufSize,
5442 const GLint *params)
5443{
5444 if (!ValidateRobustEntryPoint(context, bufSize))
5445 {
5446 return false;
5447 }
5448
5449 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5450}
5451
Geoff Lang0b031062016-10-13 14:30:04 -04005452bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5453{
5454 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5455}
5456
5457bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5458 GLuint index,
5459 GLenum pname,
5460 GLsizei bufSize,
5461 GLsizei *length,
5462 GLfloat *params)
5463{
5464 if (!ValidateRobustEntryPoint(context, bufSize))
5465 {
5466 return false;
5467 }
5468
5469 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5470 {
5471 return false;
5472 }
5473
5474 if (!ValidateRobustBufferSize(context, bufSize, *length))
5475 {
5476 return false;
5477 }
5478
5479 return true;
5480}
5481
5482bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5483{
5484 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5485}
5486
5487bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5488 GLuint index,
5489 GLenum pname,
5490 GLsizei bufSize,
5491 GLsizei *length,
5492 GLint *params)
5493{
5494 if (!ValidateRobustEntryPoint(context, bufSize))
5495 {
5496 return false;
5497 }
5498
5499 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5500 {
5501 return false;
5502 }
5503
5504 if (!ValidateRobustBufferSize(context, bufSize, *length))
5505 {
5506 return false;
5507 }
5508
5509 return true;
5510}
5511
5512bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5513{
5514 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5515}
5516
5517bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5518 GLuint index,
5519 GLenum pname,
5520 GLsizei bufSize,
5521 GLsizei *length,
5522 void **pointer)
5523{
5524 if (!ValidateRobustEntryPoint(context, bufSize))
5525 {
5526 return false;
5527 }
5528
5529 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5530 {
5531 return false;
5532 }
5533
5534 if (!ValidateRobustBufferSize(context, bufSize, *length))
5535 {
5536 return false;
5537 }
5538
5539 return true;
5540}
5541
5542bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5543{
5544 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5545}
5546
5547bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5548 GLuint index,
5549 GLenum pname,
5550 GLsizei bufSize,
5551 GLsizei *length,
5552 GLint *params)
5553{
5554 if (!ValidateRobustEntryPoint(context, bufSize))
5555 {
5556 return false;
5557 }
5558
5559 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5560 {
5561 return false;
5562 }
5563
5564 if (!ValidateRobustBufferSize(context, bufSize, *length))
5565 {
5566 return false;
5567 }
5568
5569 return true;
5570}
5571
5572bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5573{
5574 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5575}
5576
5577bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5578 GLuint index,
5579 GLenum pname,
5580 GLsizei bufSize,
5581 GLsizei *length,
5582 GLuint *params)
5583{
5584 if (!ValidateRobustEntryPoint(context, bufSize))
5585 {
5586 return false;
5587 }
5588
5589 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5590 {
5591 return false;
5592 }
5593
5594 if (!ValidateRobustBufferSize(context, bufSize, *length))
5595 {
5596 return false;
5597 }
5598
5599 return true;
5600}
5601
Geoff Lang6899b872016-10-14 11:30:13 -04005602bool ValidateGetActiveUniformBlockiv(Context *context,
5603 GLuint program,
5604 GLuint uniformBlockIndex,
5605 GLenum pname,
5606 GLint *params)
5607{
5608 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5609}
5610
5611bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5612 GLuint program,
5613 GLuint uniformBlockIndex,
5614 GLenum pname,
5615 GLsizei bufSize,
5616 GLsizei *length,
5617 GLint *params)
5618{
5619 if (!ValidateRobustEntryPoint(context, bufSize))
5620 {
5621 return false;
5622 }
5623
5624 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5625 {
5626 return false;
5627 }
5628
5629 if (!ValidateRobustBufferSize(context, bufSize, *length))
5630 {
5631 return false;
5632 }
5633
5634 return true;
5635}
5636
Geoff Lang0a9661f2016-10-20 10:59:20 -07005637bool ValidateGetInternalFormativ(Context *context,
5638 GLenum target,
5639 GLenum internalformat,
5640 GLenum pname,
5641 GLsizei bufSize,
5642 GLint *params)
5643{
5644 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5645 nullptr);
5646}
5647
5648bool ValidateGetInternalFormativRobustANGLE(Context *context,
5649 GLenum target,
5650 GLenum internalformat,
5651 GLenum pname,
5652 GLsizei bufSize,
5653 GLsizei *length,
5654 GLint *params)
5655{
5656 if (!ValidateRobustEntryPoint(context, bufSize))
5657 {
5658 return false;
5659 }
5660
5661 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5662 {
5663 return false;
5664 }
5665
5666 if (!ValidateRobustBufferSize(context, bufSize, *length))
5667 {
5668 return false;
5669 }
5670
5671 return true;
5672}
5673
Jamie Madillc29968b2016-01-20 11:17:23 -05005674} // namespace gl