blob: 3d9dba3879458593dedcf1d199e722aafd8f695b [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(
1233 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
1234 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,
1245 "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
1246 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
Jamie Madillae3000b2014-08-25 15:47:51 -04003466 if (elementArrayBuffer)
3467 {
3468 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3469
3470 GLint64 offset = reinterpret_cast<GLint64>(indices);
He Yunchaoced53ae2016-11-29 15:00:51 +08003471 GLint64 byteCount =
3472 static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count) + offset;
Jamie Madillae3000b2014-08-25 15:47:51 -04003473
3474 // check for integer overflows
3475 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3476 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3477 {
Jamie Madill437fa652016-05-03 15:13:24 -04003478 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003479 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003480 }
3481
3482 // Check for reading past the end of the bound buffer object
3483 if (byteCount > elementArrayBuffer->getSize())
3484 {
Jamie Madill437fa652016-05-03 15:13:24 -04003485 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003486 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003487 }
3488 }
Corentin Wallez327411e2016-12-09 11:09:17 -05003489 else if (context->getExtensions().webglCompatibility && count > 0)
3490 {
3491 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3492 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3493 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3494 context->handleError(
3495 Error(GL_INVALID_OPERATION, "There is no element array buffer bound and count > 0."));
3496 return false;
3497 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003498 else if (!indices)
3499 {
Corentin Wallez327411e2016-12-09 11:09:17 -05003500 // This is an application error that would normally result in a crash,
3501 // but we catch it and return an error
3502 context->handleError(
3503 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003504 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003505 }
3506
Jiajia Qind9671222016-11-29 16:30:31 +08003507 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003508 {
3509 return false;
3510 }
3511
Jamie Madill2b976812014-08-25 15:47:49 -04003512 // Use max index to validate if our vertex buffers are large enough for the pull.
3513 // TODO: offer fast path, with disabled index validation.
3514 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3515 if (elementArrayBuffer)
3516 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003517 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003518 Error error =
3519 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3520 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003521 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003522 {
Jamie Madill437fa652016-05-03 15:13:24 -04003523 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003524 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003525 }
3526 }
3527 else
3528 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003529 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003530 }
3531
Jamie Madille79b1e12015-11-04 16:36:37 -05003532 // If we use an index greater than our maximum supported index range, return an error.
3533 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3534 // return an error if possible here.
3535 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3536 {
Jamie Madill437fa652016-05-03 15:13:24 -04003537 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003538 return false;
3539 }
3540
Corentin Wallez92db6942016-12-09 13:10:36 -05003541 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3542 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003543 {
3544 return false;
3545 }
3546
Geoff Lang3edfe032015-09-04 16:38:24 -04003547 // No op if there are no real indices in the index data (all are primitive restart).
3548 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003549}
3550
Geoff Langb1196682014-07-23 13:47:29 -04003551bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003552 GLenum mode,
3553 GLsizei count,
3554 GLenum type,
3555 const GLvoid *indices,
3556 GLsizei primcount,
3557 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003558{
3559 if (primcount < 0)
3560 {
Jamie Madill437fa652016-05-03 15:13:24 -04003561 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003562 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003563 }
3564
Jamie Madill2b976812014-08-25 15:47:49 -04003565 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003566 {
3567 return false;
3568 }
3569
3570 // No-op zero primitive count
3571 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003572}
3573
Geoff Lang3edfe032015-09-04 16:38:24 -04003574bool ValidateDrawElementsInstancedANGLE(Context *context,
3575 GLenum mode,
3576 GLsizei count,
3577 GLenum type,
3578 const GLvoid *indices,
3579 GLsizei primcount,
3580 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003581{
3582 if (!ValidateDrawInstancedANGLE(context))
3583 {
3584 return false;
3585 }
3586
He Yunchaoced53ae2016-11-29 15:00:51 +08003587 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3588 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003589}
3590
He Yunchaoced53ae2016-11-29 15:00:51 +08003591bool ValidateFramebufferTextureBase(Context *context,
3592 GLenum target,
3593 GLenum attachment,
3594 GLuint texture,
3595 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003596{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003597 if (!ValidFramebufferTarget(target))
3598 {
Jamie Madill437fa652016-05-03 15:13:24 -04003599 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003600 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003601 }
3602
3603 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003604 {
3605 return false;
3606 }
3607
Jamie Madill55ec3b12014-07-03 10:38:57 -04003608 if (texture != 0)
3609 {
3610 gl::Texture *tex = context->getTexture(texture);
3611
3612 if (tex == NULL)
3613 {
Jamie Madill437fa652016-05-03 15:13:24 -04003614 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003615 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003616 }
3617
3618 if (level < 0)
3619 {
Jamie Madill437fa652016-05-03 15:13:24 -04003620 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003621 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003622 }
3623 }
3624
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003625 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003626 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003627
Jamie Madill84115c92015-04-23 15:00:07 -04003628 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003629 {
Jamie Madill437fa652016-05-03 15:13:24 -04003630 context->handleError(
3631 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003632 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003633 }
3634
3635 return true;
3636}
3637
He Yunchaoced53ae2016-11-29 15:00:51 +08003638bool ValidateFramebufferTexture2D(Context *context,
3639 GLenum target,
3640 GLenum attachment,
3641 GLenum textarget,
3642 GLuint texture,
3643 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003644{
He Yunchaoced53ae2016-11-29 15:00:51 +08003645 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3646 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003647 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3648 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003649 {
Jamie Madill437fa652016-05-03 15:13:24 -04003650 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003651 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003652 }
3653
3654 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003655 {
3656 return false;
3657 }
3658
Jamie Madill55ec3b12014-07-03 10:38:57 -04003659 if (texture != 0)
3660 {
3661 gl::Texture *tex = context->getTexture(texture);
3662 ASSERT(tex);
3663
Jamie Madill2a6564e2014-07-11 09:53:19 -04003664 const gl::Caps &caps = context->getCaps();
3665
Jamie Madill55ec3b12014-07-03 10:38:57 -04003666 switch (textarget)
3667 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003668 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003669 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003670 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003671 {
Jamie Madill437fa652016-05-03 15:13:24 -04003672 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003673 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003674 }
3675 if (tex->getTarget() != GL_TEXTURE_2D)
3676 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003677 context->handleError(Error(GL_INVALID_OPERATION,
3678 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003679 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003680 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003681 }
3682 break;
3683
He Yunchaoced53ae2016-11-29 15:00:51 +08003684 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3685 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3686 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3687 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3688 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3689 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003690 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003691 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003692 {
Jamie Madill437fa652016-05-03 15:13:24 -04003693 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003694 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003695 }
3696 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3697 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003698 context->handleError(Error(GL_INVALID_OPERATION,
3699 "Textarget must match the texture target type."));
3700 return false;
3701 }
3702 }
3703 break;
3704
3705 case GL_TEXTURE_2D_MULTISAMPLE:
3706 {
3707 if (context->getClientVersion() < ES_3_1)
3708 {
3709 context->handleError(Error(GL_INVALID_OPERATION,
3710 "Texture target requires at least OpenGL ES 3.1."));
3711 return false;
3712 }
3713
3714 if (level != 0)
3715 {
3716 context->handleError(
3717 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
3718 return false;
3719 }
3720 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
3721 {
3722 context->handleError(Error(GL_INVALID_OPERATION,
3723 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003724 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003725 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003726 }
3727 break;
3728
He Yunchaoced53ae2016-11-29 15:00:51 +08003729 default:
3730 context->handleError(Error(GL_INVALID_ENUM));
3731 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003732 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003733
Jamie Madilla3944d42016-07-22 22:13:26 -04003734 const Format &format = tex->getFormat(textarget, level);
3735 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003736 {
Jamie Madill437fa652016-05-03 15:13:24 -04003737 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003738 return false;
3739 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003740 }
3741
Jamie Madill570f7c82014-07-03 10:38:54 -04003742 return true;
3743}
3744
Geoff Langb1196682014-07-23 13:47:29 -04003745bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003746{
3747 if (program == 0)
3748 {
Jamie Madill437fa652016-05-03 15:13:24 -04003749 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003750 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003751 }
3752
Dian Xiang769769a2015-09-09 15:20:08 -07003753 gl::Program *programObject = GetValidProgram(context, program);
3754 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003755 {
3756 return false;
3757 }
3758
Jamie Madill0063c512014-08-25 15:47:53 -04003759 if (!programObject || !programObject->isLinked())
3760 {
Jamie Madill437fa652016-05-03 15:13:24 -04003761 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003762 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003763 }
3764
Geoff Lang7dd2e102014-11-10 15:19:26 -05003765 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003766 {
Jamie Madill437fa652016-05-03 15:13:24 -04003767 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003768 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003769 }
3770
Jamie Madill0063c512014-08-25 15:47:53 -04003771 return true;
3772}
3773
He Yunchaoced53ae2016-11-29 15:00:51 +08003774bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003775{
3776 return ValidateGetUniformBase(context, program, location);
3777}
3778
He Yunchaoced53ae2016-11-29 15:00:51 +08003779bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003780{
Jamie Madill78f41802014-08-25 15:47:55 -04003781 return ValidateGetUniformBase(context, program, location);
3782}
3783
Geoff Langf41d0ee2016-10-07 13:04:23 -04003784static bool ValidateSizedGetUniform(Context *context,
3785 GLuint program,
3786 GLint location,
3787 GLsizei bufSize,
3788 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003789{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003790 if (length)
3791 {
3792 *length = 0;
3793 }
3794
Jamie Madill78f41802014-08-25 15:47:55 -04003795 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003796 {
Jamie Madill78f41802014-08-25 15:47:55 -04003797 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003798 }
3799
Geoff Langf41d0ee2016-10-07 13:04:23 -04003800 if (bufSize < 0)
3801 {
3802 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3803 return false;
3804 }
3805
Jamie Madilla502c742014-08-28 17:19:13 -04003806 gl::Program *programObject = context->getProgram(program);
3807 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003808
Jamie Madill78f41802014-08-25 15:47:55 -04003809 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003810 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003811 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003812 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003813 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003814 context->handleError(
3815 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003816 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003817 }
3818
Geoff Langf41d0ee2016-10-07 13:04:23 -04003819 if (length)
3820 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003821 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003822 }
3823
Jamie Madill0063c512014-08-25 15:47:53 -04003824 return true;
3825}
3826
He Yunchaoced53ae2016-11-29 15:00:51 +08003827bool ValidateGetnUniformfvEXT(Context *context,
3828 GLuint program,
3829 GLint location,
3830 GLsizei bufSize,
3831 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003832{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003833 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003834}
3835
He Yunchaoced53ae2016-11-29 15:00:51 +08003836bool ValidateGetnUniformivEXT(Context *context,
3837 GLuint program,
3838 GLint location,
3839 GLsizei bufSize,
3840 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003841{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003842 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3843}
3844
3845bool ValidateGetUniformfvRobustANGLE(Context *context,
3846 GLuint program,
3847 GLint location,
3848 GLsizei bufSize,
3849 GLsizei *length,
3850 GLfloat *params)
3851{
3852 if (!ValidateRobustEntryPoint(context, bufSize))
3853 {
3854 return false;
3855 }
3856
3857 // bufSize is validated in ValidateSizedGetUniform
3858 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3859}
3860
3861bool ValidateGetUniformivRobustANGLE(Context *context,
3862 GLuint program,
3863 GLint location,
3864 GLsizei bufSize,
3865 GLsizei *length,
3866 GLint *params)
3867{
3868 if (!ValidateRobustEntryPoint(context, bufSize))
3869 {
3870 return false;
3871 }
3872
3873 // bufSize is validated in ValidateSizedGetUniform
3874 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3875}
3876
3877bool ValidateGetUniformuivRobustANGLE(Context *context,
3878 GLuint program,
3879 GLint location,
3880 GLsizei bufSize,
3881 GLsizei *length,
3882 GLuint *params)
3883{
3884 if (!ValidateRobustEntryPoint(context, bufSize))
3885 {
3886 return false;
3887 }
3888
3889 if (context->getClientMajorVersion() < 3)
3890 {
3891 context->handleError(
3892 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3893 return false;
3894 }
3895
3896 // bufSize is validated in ValidateSizedGetUniform
3897 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003898}
3899
He Yunchaoced53ae2016-11-29 15:00:51 +08003900bool ValidateDiscardFramebufferBase(Context *context,
3901 GLenum target,
3902 GLsizei numAttachments,
3903 const GLenum *attachments,
3904 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003905{
3906 if (numAttachments < 0)
3907 {
Jamie Madill437fa652016-05-03 15:13:24 -04003908 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003909 return false;
3910 }
3911
3912 for (GLsizei i = 0; i < numAttachments; ++i)
3913 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003914 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003915 {
3916 if (defaultFramebuffer)
3917 {
Jamie Madill437fa652016-05-03 15:13:24 -04003918 context->handleError(Error(
3919 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003920 return false;
3921 }
3922
3923 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3924 {
Jamie Madill437fa652016-05-03 15:13:24 -04003925 context->handleError(Error(GL_INVALID_OPERATION,
3926 "Requested color attachment is greater than the maximum "
3927 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003928 return false;
3929 }
3930 }
3931 else
3932 {
3933 switch (attachments[i])
3934 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003935 case GL_DEPTH_ATTACHMENT:
3936 case GL_STENCIL_ATTACHMENT:
3937 case GL_DEPTH_STENCIL_ATTACHMENT:
3938 if (defaultFramebuffer)
3939 {
3940 context->handleError(
3941 Error(GL_INVALID_ENUM,
3942 "Invalid attachment when the default framebuffer is bound"));
3943 return false;
3944 }
3945 break;
3946 case GL_COLOR:
3947 case GL_DEPTH:
3948 case GL_STENCIL:
3949 if (!defaultFramebuffer)
3950 {
3951 context->handleError(
3952 Error(GL_INVALID_ENUM,
3953 "Invalid attachment when the default framebuffer is not bound"));
3954 return false;
3955 }
3956 break;
3957 default:
3958 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003959 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003960 }
3961 }
3962 }
3963
3964 return true;
3965}
3966
Austin Kinross6ee1e782015-05-29 17:05:37 -07003967bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3968{
3969 // Note that debug marker calls must not set error state
3970
3971 if (length < 0)
3972 {
3973 return false;
3974 }
3975
3976 if (marker == nullptr)
3977 {
3978 return false;
3979 }
3980
3981 return true;
3982}
3983
3984bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3985{
3986 // Note that debug marker calls must not set error state
3987
3988 if (length < 0)
3989 {
3990 return false;
3991 }
3992
3993 if (length > 0 && marker == nullptr)
3994 {
3995 return false;
3996 }
3997
3998 return true;
3999}
4000
Geoff Langdcab33b2015-07-21 13:03:16 -04004001bool ValidateEGLImageTargetTexture2DOES(Context *context,
4002 egl::Display *display,
4003 GLenum target,
4004 egl::Image *image)
4005{
Geoff Langa8406172015-07-21 16:53:39 -04004006 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4007 {
Jamie Madill437fa652016-05-03 15:13:24 -04004008 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004009 return false;
4010 }
4011
4012 switch (target)
4013 {
4014 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004015 if (!context->getExtensions().eglImage)
4016 {
4017 context->handleError(Error(
4018 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4019 }
4020 break;
4021
4022 case GL_TEXTURE_EXTERNAL_OES:
4023 if (!context->getExtensions().eglImageExternal)
4024 {
4025 context->handleError(Error(
4026 GL_INVALID_ENUM,
4027 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4028 }
Geoff Langa8406172015-07-21 16:53:39 -04004029 break;
4030
4031 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004032 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004033 return false;
4034 }
4035
4036 if (!display->isValidImage(image))
4037 {
Jamie Madill437fa652016-05-03 15:13:24 -04004038 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004039 return false;
4040 }
4041
4042 if (image->getSamples() > 0)
4043 {
Jamie Madill437fa652016-05-03 15:13:24 -04004044 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004045 "cannot create a 2D texture from a multisampled EGL image."));
4046 return false;
4047 }
4048
Jamie Madilla3944d42016-07-22 22:13:26 -04004049 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004050 if (!textureCaps.texturable)
4051 {
Jamie Madill437fa652016-05-03 15:13:24 -04004052 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004053 "EGL image internal format is not supported as a texture."));
4054 return false;
4055 }
4056
Geoff Langdcab33b2015-07-21 13:03:16 -04004057 return true;
4058}
4059
4060bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4061 egl::Display *display,
4062 GLenum target,
4063 egl::Image *image)
4064{
Geoff Langa8406172015-07-21 16:53:39 -04004065 if (!context->getExtensions().eglImage)
4066 {
Jamie Madill437fa652016-05-03 15:13:24 -04004067 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004068 return false;
4069 }
4070
4071 switch (target)
4072 {
4073 case GL_RENDERBUFFER:
4074 break;
4075
4076 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004077 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004078 return false;
4079 }
4080
4081 if (!display->isValidImage(image))
4082 {
Jamie Madill437fa652016-05-03 15:13:24 -04004083 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004084 return false;
4085 }
4086
Jamie Madilla3944d42016-07-22 22:13:26 -04004087 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004088 if (!textureCaps.renderable)
4089 {
Jamie Madill437fa652016-05-03 15:13:24 -04004090 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004091 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4092 return false;
4093 }
4094
Geoff Langdcab33b2015-07-21 13:03:16 -04004095 return true;
4096}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004097
4098bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4099{
Geoff Lang36167ab2015-12-07 10:27:14 -05004100 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004101 {
4102 // The default VAO should always exist
4103 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004104 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004105 return false;
4106 }
4107
4108 return true;
4109}
4110
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004111bool ValidateLinkProgram(Context *context, GLuint program)
4112{
4113 if (context->hasActiveTransformFeedback(program))
4114 {
4115 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004116 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004117 "Cannot link program while program is associated with an active "
4118 "transform feedback object."));
4119 return false;
4120 }
4121 return true;
4122}
4123
Geoff Langc5629752015-12-07 16:29:04 -05004124bool ValidateProgramBinaryBase(Context *context,
4125 GLuint program,
4126 GLenum binaryFormat,
4127 const void *binary,
4128 GLint length)
4129{
4130 Program *programObject = GetValidProgram(context, program);
4131 if (programObject == nullptr)
4132 {
4133 return false;
4134 }
4135
4136 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4137 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4138 programBinaryFormats.end())
4139 {
Jamie Madill437fa652016-05-03 15:13:24 -04004140 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004141 return false;
4142 }
4143
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004144 if (context->hasActiveTransformFeedback(program))
4145 {
4146 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004147 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004148 "Cannot change program binary while program is associated with "
4149 "an active transform feedback object."));
4150 return false;
4151 }
4152
Geoff Langc5629752015-12-07 16:29:04 -05004153 return true;
4154}
4155
4156bool ValidateGetProgramBinaryBase(Context *context,
4157 GLuint program,
4158 GLsizei bufSize,
4159 GLsizei *length,
4160 GLenum *binaryFormat,
4161 void *binary)
4162{
4163 Program *programObject = GetValidProgram(context, program);
4164 if (programObject == nullptr)
4165 {
4166 return false;
4167 }
4168
4169 if (!programObject->isLinked())
4170 {
Jamie Madill437fa652016-05-03 15:13:24 -04004171 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004172 return false;
4173 }
4174
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004175 if (context->getCaps().programBinaryFormats.empty())
4176 {
4177 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4178 return false;
4179 }
4180
Geoff Langc5629752015-12-07 16:29:04 -05004181 return true;
4182}
Jamie Madillc29968b2016-01-20 11:17:23 -05004183
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004184bool ValidateUseProgram(Context *context, GLuint program)
4185{
4186 if (program != 0)
4187 {
4188 Program *programObject = context->getProgram(program);
4189 if (!programObject)
4190 {
4191 // ES 3.1.0 section 7.3 page 72
4192 if (context->getShader(program))
4193 {
Jamie Madill437fa652016-05-03 15:13:24 -04004194 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004195 Error(GL_INVALID_OPERATION,
4196 "Attempted to use a single shader instead of a shader program."));
4197 return false;
4198 }
4199 else
4200 {
Jamie Madill437fa652016-05-03 15:13:24 -04004201 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004202 return false;
4203 }
4204 }
4205 if (!programObject->isLinked())
4206 {
Jamie Madill437fa652016-05-03 15:13:24 -04004207 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004208 return false;
4209 }
4210 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004211 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004212 {
4213 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004214 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004215 Error(GL_INVALID_OPERATION,
4216 "Cannot change active program while transform feedback is unpaused."));
4217 return false;
4218 }
4219
4220 return true;
4221}
4222
Jamie Madillc29968b2016-01-20 11:17:23 -05004223bool ValidateCopyTexImage2D(ValidationContext *context,
4224 GLenum target,
4225 GLint level,
4226 GLenum internalformat,
4227 GLint x,
4228 GLint y,
4229 GLsizei width,
4230 GLsizei height,
4231 GLint border)
4232{
Martin Radev1be913c2016-07-11 17:59:16 +03004233 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004234 {
4235 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4236 0, x, y, width, height, border);
4237 }
4238
Martin Radev1be913c2016-07-11 17:59:16 +03004239 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004240 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4241 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004242}
Jamie Madillc29968b2016-01-20 11:17:23 -05004243
4244bool ValidateFramebufferRenderbuffer(Context *context,
4245 GLenum target,
4246 GLenum attachment,
4247 GLenum renderbuffertarget,
4248 GLuint renderbuffer)
4249{
4250 if (!ValidFramebufferTarget(target) ||
4251 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4252 {
Jamie Madill437fa652016-05-03 15:13:24 -04004253 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004254 return false;
4255 }
4256
4257 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4258 renderbuffertarget, renderbuffer);
4259}
4260
4261bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4262{
4263 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4264 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4265 {
Jamie Madill437fa652016-05-03 15:13:24 -04004266 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004267 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4268 return false;
4269 }
4270
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004271 ASSERT(context->getGLState().getDrawFramebuffer());
4272 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004273 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4274
4275 // This should come first before the check for the default frame buffer
4276 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4277 // rather than INVALID_OPERATION
4278 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4279 {
4280 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4281
4282 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004283 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4284 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004285 {
4286 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004287 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4288 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4289 // 3.1 is still a bit ambiguous about the error, but future specs are
4290 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004291 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004292 return false;
4293 }
4294 else if (bufs[colorAttachment] >= maxColorAttachment)
4295 {
Jamie Madill437fa652016-05-03 15:13:24 -04004296 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004297 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004298 return false;
4299 }
4300 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4301 frameBufferId != 0)
4302 {
4303 // INVALID_OPERATION-GL is bound to buffer and ith argument
4304 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004305 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004306 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4307 return false;
4308 }
4309 }
4310
4311 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4312 // and n is not 1 or bufs is bound to value other than BACK and NONE
4313 if (frameBufferId == 0)
4314 {
4315 if (n != 1)
4316 {
Jamie Madill437fa652016-05-03 15:13:24 -04004317 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004318 "n must be 1 when GL is bound to the default framebuffer"));
4319 return false;
4320 }
4321
4322 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4323 {
Jamie Madill437fa652016-05-03 15:13:24 -04004324 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004325 GL_INVALID_OPERATION,
4326 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4327 return false;
4328 }
4329 }
4330
4331 return true;
4332}
4333
4334bool ValidateCopyTexSubImage2D(Context *context,
4335 GLenum target,
4336 GLint level,
4337 GLint xoffset,
4338 GLint yoffset,
4339 GLint x,
4340 GLint y,
4341 GLsizei width,
4342 GLsizei height)
4343{
Martin Radev1be913c2016-07-11 17:59:16 +03004344 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004345 {
4346 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4347 yoffset, x, y, width, height, 0);
4348 }
4349
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004350 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4351 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004352}
4353
Geoff Lang496c02d2016-10-20 11:38:11 -07004354bool ValidateGetBufferPointervBase(Context *context,
4355 GLenum target,
4356 GLenum pname,
4357 GLsizei *length,
4358 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004359{
Geoff Lang496c02d2016-10-20 11:38:11 -07004360 if (length)
4361 {
4362 *length = 0;
4363 }
4364
4365 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4366 {
4367 context->handleError(
4368 Error(GL_INVALID_OPERATION,
4369 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
4370 return false;
4371 }
4372
Olli Etuaho4f667482016-03-30 15:56:35 +03004373 if (!ValidBufferTarget(context, target))
4374 {
Jamie Madill437fa652016-05-03 15:13:24 -04004375 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004376 return false;
4377 }
4378
Geoff Lang496c02d2016-10-20 11:38:11 -07004379 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004380 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004381 case GL_BUFFER_MAP_POINTER:
4382 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004383
Geoff Lang496c02d2016-10-20 11:38:11 -07004384 default:
4385 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4386 return false;
4387 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004388
4389 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4390 // target bound to zero generate an INVALID_OPERATION error."
4391 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004392 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004393 {
Jamie Madill437fa652016-05-03 15:13:24 -04004394 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004395 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4396 return false;
4397 }
4398
Geoff Lang496c02d2016-10-20 11:38:11 -07004399 if (length)
4400 {
4401 *length = 1;
4402 }
4403
Olli Etuaho4f667482016-03-30 15:56:35 +03004404 return true;
4405}
4406
4407bool ValidateUnmapBufferBase(Context *context, GLenum target)
4408{
4409 if (!ValidBufferTarget(context, target))
4410 {
Jamie Madill437fa652016-05-03 15:13:24 -04004411 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004412 return false;
4413 }
4414
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004415 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004416
4417 if (buffer == nullptr || !buffer->isMapped())
4418 {
Jamie Madill437fa652016-05-03 15:13:24 -04004419 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004420 return false;
4421 }
4422
4423 return true;
4424}
4425
4426bool ValidateMapBufferRangeBase(Context *context,
4427 GLenum target,
4428 GLintptr offset,
4429 GLsizeiptr length,
4430 GLbitfield access)
4431{
4432 if (!ValidBufferTarget(context, target))
4433 {
Jamie Madill437fa652016-05-03 15:13:24 -04004434 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004435 return false;
4436 }
4437
4438 if (offset < 0 || length < 0)
4439 {
Jamie Madill437fa652016-05-03 15:13:24 -04004440 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004441 return false;
4442 }
4443
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004444 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004445
4446 if (!buffer)
4447 {
Jamie Madill437fa652016-05-03 15:13:24 -04004448 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004449 return false;
4450 }
4451
4452 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004453 CheckedNumeric<size_t> checkedOffset(offset);
4454 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004455
Jamie Madille2e406c2016-06-02 13:04:10 -04004456 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004457 {
Jamie Madill437fa652016-05-03 15:13:24 -04004458 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004459 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4460 return false;
4461 }
4462
4463 // Check for invalid bits in the mask
4464 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4465 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4466 GL_MAP_UNSYNCHRONIZED_BIT;
4467
4468 if (access & ~(allAccessBits))
4469 {
Jamie Madill437fa652016-05-03 15:13:24 -04004470 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004471 return false;
4472 }
4473
4474 if (length == 0)
4475 {
Jamie Madill437fa652016-05-03 15:13:24 -04004476 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004477 return false;
4478 }
4479
4480 if (buffer->isMapped())
4481 {
Jamie Madill437fa652016-05-03 15:13:24 -04004482 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004483 return false;
4484 }
4485
4486 // Check for invalid bit combinations
4487 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4488 {
Jamie Madill437fa652016-05-03 15:13:24 -04004489 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004490 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4491 return false;
4492 }
4493
4494 GLbitfield writeOnlyBits =
4495 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4496
4497 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4498 {
Jamie Madill437fa652016-05-03 15:13:24 -04004499 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004500 "Invalid access bits when mapping buffer for reading: 0x%X.",
4501 access));
4502 return false;
4503 }
4504
4505 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4506 {
Jamie Madill437fa652016-05-03 15:13:24 -04004507 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004508 GL_INVALID_OPERATION,
4509 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4510 return false;
4511 }
4512 return true;
4513}
4514
4515bool ValidateFlushMappedBufferRangeBase(Context *context,
4516 GLenum target,
4517 GLintptr offset,
4518 GLsizeiptr length)
4519{
4520 if (offset < 0 || length < 0)
4521 {
Jamie Madill437fa652016-05-03 15:13:24 -04004522 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004523 return false;
4524 }
4525
4526 if (!ValidBufferTarget(context, target))
4527 {
Jamie Madill437fa652016-05-03 15:13:24 -04004528 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004529 return false;
4530 }
4531
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004532 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004533
4534 if (buffer == nullptr)
4535 {
Jamie Madill437fa652016-05-03 15:13:24 -04004536 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004537 return false;
4538 }
4539
4540 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4541 {
Jamie Madill437fa652016-05-03 15:13:24 -04004542 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004543 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4544 return false;
4545 }
4546
4547 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004548 CheckedNumeric<size_t> checkedOffset(offset);
4549 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004550
Jamie Madille2e406c2016-06-02 13:04:10 -04004551 if (!checkedSize.IsValid() ||
4552 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004553 {
Jamie Madill437fa652016-05-03 15:13:24 -04004554 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004555 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4556 return false;
4557 }
4558
4559 return true;
4560}
4561
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004562bool ValidateGenerateMipmap(Context *context, GLenum target)
4563{
4564 if (!ValidTextureTarget(context, target))
4565 {
4566 context->handleError(Error(GL_INVALID_ENUM));
4567 return false;
4568 }
4569
4570 Texture *texture = context->getTargetTexture(target);
4571
4572 if (texture == nullptr)
4573 {
4574 context->handleError(Error(GL_INVALID_OPERATION));
4575 return false;
4576 }
4577
4578 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4579
4580 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4581 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4582 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4583 {
4584 context->handleError(Error(GL_INVALID_OPERATION));
4585 return false;
4586 }
4587
Jamie Madilla3944d42016-07-22 22:13:26 -04004588 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4589 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4590 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004591
4592 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4593 // unsized formats or that are color renderable and filterable. Since we do not track if
4594 // the texture was created with sized or unsized format (only sized formats are stored),
4595 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4596 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4597 // textures since they're the only texture format that can be created with unsized formats
4598 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4599 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004600 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4601 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004602 {
4603 context->handleError(Error(GL_INVALID_OPERATION));
4604 return false;
4605 }
4606
4607 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004608 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004609 {
4610 context->handleError(Error(GL_INVALID_OPERATION));
4611 return false;
4612 }
4613
4614 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004615 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004616 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4617 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4618 {
Geoff Lang55482a12016-11-21 16:54:01 -05004619 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004620 context->handleError(Error(GL_INVALID_OPERATION));
4621 return false;
4622 }
4623
4624 // Cube completeness check
4625 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4626 {
4627 context->handleError(Error(GL_INVALID_OPERATION));
4628 return false;
4629 }
4630
4631 return true;
4632}
4633
Olli Etuaho41997e72016-03-10 13:38:39 +02004634bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4635{
4636 return ValidateGenOrDelete(context, n);
4637}
4638
4639bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4640{
4641 return ValidateGenOrDelete(context, n);
4642}
4643
4644bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4645{
4646 return ValidateGenOrDelete(context, n);
4647}
4648
4649bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4650{
4651 return ValidateGenOrDelete(context, n);
4652}
4653
4654bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4655{
4656 return ValidateGenOrDelete(context, n);
4657}
4658
4659bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4660{
4661 return ValidateGenOrDelete(context, n);
4662}
4663
4664bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4665{
4666 return ValidateGenOrDelete(context, n);
4667}
4668
4669bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4670{
4671 return ValidateGenOrDelete(context, n);
4672}
4673
4674bool ValidateGenOrDelete(Context *context, GLint n)
4675{
4676 if (n < 0)
4677 {
Jamie Madill437fa652016-05-03 15:13:24 -04004678 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004679 return false;
4680 }
4681 return true;
4682}
4683
Geoff Langf41a7152016-09-19 15:11:17 -04004684bool ValidateEnable(Context *context, GLenum cap)
4685{
4686 if (!ValidCap(context, cap, false))
4687 {
4688 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4689 return false;
4690 }
4691
4692 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4693 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4694 {
4695 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4696 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4697
4698 // We also output an error message to the debugger window if tracing is active, so that
4699 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05004700 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04004701 return false;
4702 }
4703
4704 return true;
4705}
4706
4707bool ValidateDisable(Context *context, GLenum cap)
4708{
4709 if (!ValidCap(context, cap, false))
4710 {
4711 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4712 return false;
4713 }
4714
4715 return true;
4716}
4717
4718bool ValidateIsEnabled(Context *context, GLenum cap)
4719{
4720 if (!ValidCap(context, cap, true))
4721 {
4722 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4723 return false;
4724 }
4725
4726 return true;
4727}
4728
Geoff Langff5b2d52016-09-07 11:32:23 -04004729bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4730{
4731 if (!context->getExtensions().robustClientMemory)
4732 {
4733 context->handleError(
4734 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4735 return false;
4736 }
4737
4738 if (bufSize < 0)
4739 {
4740 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4741 return false;
4742 }
4743
4744 return true;
4745}
4746
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004747bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4748{
4749 if (bufSize < numParams)
4750 {
4751 context->handleError(Error(GL_INVALID_OPERATION,
4752 "%u parameters are required but %i were provided.", numParams,
4753 bufSize));
4754 return false;
4755 }
4756
4757 return true;
4758}
4759
Geoff Langff5b2d52016-09-07 11:32:23 -04004760bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4761 GLenum target,
4762 GLenum attachment,
4763 GLenum pname,
4764 GLsizei *numParams)
4765{
4766 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4767 *numParams = 1;
4768
4769 if (!ValidFramebufferTarget(target))
4770 {
4771 context->handleError(Error(GL_INVALID_ENUM));
4772 return false;
4773 }
4774
4775 int clientVersion = context->getClientMajorVersion();
4776
4777 switch (pname)
4778 {
4779 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4780 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4781 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4782 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4783 break;
4784
4785 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4786 if (clientVersion < 3 && !context->getExtensions().sRGB)
4787 {
4788 context->handleError(Error(GL_INVALID_ENUM));
4789 return false;
4790 }
4791 break;
4792
4793 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4794 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4795 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4796 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4797 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4798 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4799 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4800 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4801 if (clientVersion < 3)
4802 {
4803 context->handleError(Error(GL_INVALID_ENUM));
4804 return false;
4805 }
4806 break;
4807
4808 default:
4809 context->handleError(Error(GL_INVALID_ENUM));
4810 return false;
4811 }
4812
4813 // Determine if the attachment is a valid enum
4814 switch (attachment)
4815 {
4816 case GL_BACK:
4817 case GL_FRONT:
4818 case GL_DEPTH:
4819 case GL_STENCIL:
4820 case GL_DEPTH_STENCIL_ATTACHMENT:
4821 if (clientVersion < 3)
4822 {
4823 context->handleError(Error(GL_INVALID_ENUM));
4824 return false;
4825 }
4826 break;
4827
4828 case GL_DEPTH_ATTACHMENT:
4829 case GL_STENCIL_ATTACHMENT:
4830 break;
4831
4832 default:
4833 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4834 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4835 {
4836 context->handleError(Error(GL_INVALID_ENUM));
4837 return false;
4838 }
4839 break;
4840 }
4841
4842 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4843 ASSERT(framebuffer);
4844
4845 if (framebuffer->id() == 0)
4846 {
4847 if (clientVersion < 3)
4848 {
4849 context->handleError(Error(GL_INVALID_OPERATION));
4850 return false;
4851 }
4852
4853 switch (attachment)
4854 {
4855 case GL_BACK:
4856 case GL_DEPTH:
4857 case GL_STENCIL:
4858 break;
4859
4860 default:
4861 context->handleError(Error(GL_INVALID_OPERATION));
4862 return false;
4863 }
4864 }
4865 else
4866 {
4867 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4868 {
4869 // Valid attachment query
4870 }
4871 else
4872 {
4873 switch (attachment)
4874 {
4875 case GL_DEPTH_ATTACHMENT:
4876 case GL_STENCIL_ATTACHMENT:
4877 break;
4878
4879 case GL_DEPTH_STENCIL_ATTACHMENT:
4880 if (!framebuffer->hasValidDepthStencil())
4881 {
4882 context->handleError(Error(GL_INVALID_OPERATION));
4883 return false;
4884 }
4885 break;
4886
4887 default:
4888 context->handleError(Error(GL_INVALID_OPERATION));
4889 return false;
4890 }
4891 }
4892 }
4893
4894 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4895 if (attachmentObject)
4896 {
4897 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4898 attachmentObject->type() == GL_TEXTURE ||
4899 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4900
4901 switch (pname)
4902 {
4903 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4904 if (attachmentObject->type() != GL_RENDERBUFFER &&
4905 attachmentObject->type() != GL_TEXTURE)
4906 {
4907 context->handleError(Error(GL_INVALID_ENUM));
4908 return false;
4909 }
4910 break;
4911
4912 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4913 if (attachmentObject->type() != GL_TEXTURE)
4914 {
4915 context->handleError(Error(GL_INVALID_ENUM));
4916 return false;
4917 }
4918 break;
4919
4920 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4921 if (attachmentObject->type() != GL_TEXTURE)
4922 {
4923 context->handleError(Error(GL_INVALID_ENUM));
4924 return false;
4925 }
4926 break;
4927
4928 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4929 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4930 {
4931 context->handleError(Error(GL_INVALID_OPERATION));
4932 return false;
4933 }
4934 break;
4935
4936 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4937 if (attachmentObject->type() != GL_TEXTURE)
4938 {
4939 context->handleError(Error(GL_INVALID_ENUM));
4940 return false;
4941 }
4942 break;
4943
4944 default:
4945 break;
4946 }
4947 }
4948 else
4949 {
4950 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4951 // is NONE, then querying any other pname will generate INVALID_ENUM.
4952
4953 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4954 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4955 // INVALID_OPERATION for all other pnames
4956
4957 switch (pname)
4958 {
4959 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4960 break;
4961
4962 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4963 if (clientVersion < 3)
4964 {
4965 context->handleError(Error(GL_INVALID_ENUM));
4966 return false;
4967 }
4968 break;
4969
4970 default:
4971 if (clientVersion < 3)
4972 {
4973 context->handleError(Error(GL_INVALID_ENUM));
4974 return false;
4975 }
4976 else
4977 {
4978 context->handleError(Error(GL_INVALID_OPERATION));
4979 return false;
4980 }
4981 }
4982 }
4983
4984 return true;
4985}
4986
4987bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4988 GLenum target,
4989 GLenum attachment,
4990 GLenum pname,
4991 GLsizei bufSize,
4992 GLsizei *numParams)
4993{
4994 if (!ValidateRobustEntryPoint(context, bufSize))
4995 {
4996 return false;
4997 }
4998
4999 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5000 {
5001 return false;
5002 }
5003
5004 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5005 {
5006 return false;
5007 }
5008
5009 return true;
5010}
5011
5012bool ValidateGetBufferParameteriv(ValidationContext *context,
5013 GLenum target,
5014 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005015 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005016{
Geoff Langebebe1c2016-10-14 12:01:31 -04005017 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005018}
5019
5020bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5021 GLenum target,
5022 GLenum pname,
5023 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005024 GLsizei *length,
5025 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005026{
5027 if (!ValidateRobustEntryPoint(context, bufSize))
5028 {
5029 return false;
5030 }
5031
Geoff Langebebe1c2016-10-14 12:01:31 -04005032 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005033 {
5034 return false;
5035 }
5036
Geoff Langebebe1c2016-10-14 12:01:31 -04005037 if (!ValidateRobustBufferSize(context, bufSize, *length))
5038 {
5039 return false;
5040 }
5041
5042 return true;
5043}
5044
5045bool ValidateGetBufferParameteri64v(ValidationContext *context,
5046 GLenum target,
5047 GLenum pname,
5048 GLint64 *params)
5049{
5050 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5051}
5052
5053bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5054 GLenum target,
5055 GLenum pname,
5056 GLsizei bufSize,
5057 GLsizei *length,
5058 GLint64 *params)
5059{
5060 if (!ValidateRobustEntryPoint(context, bufSize))
5061 {
5062 return false;
5063 }
5064
5065 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5066 {
5067 return false;
5068 }
5069
5070 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005071 {
5072 return false;
5073 }
5074
5075 return true;
5076}
5077
5078bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5079{
5080 // Currently, all GetProgramiv queries return 1 parameter
5081 *numParams = 1;
5082
5083 Program *programObject = GetValidProgram(context, program);
5084 if (!programObject)
5085 {
5086 return false;
5087 }
5088
5089 switch (pname)
5090 {
5091 case GL_DELETE_STATUS:
5092 case GL_LINK_STATUS:
5093 case GL_VALIDATE_STATUS:
5094 case GL_INFO_LOG_LENGTH:
5095 case GL_ATTACHED_SHADERS:
5096 case GL_ACTIVE_ATTRIBUTES:
5097 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5098 case GL_ACTIVE_UNIFORMS:
5099 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5100 break;
5101
5102 case GL_PROGRAM_BINARY_LENGTH:
5103 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5104 {
5105 context->handleError(Error(GL_INVALID_ENUM,
5106 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5107 "GL_OES_get_program_binary or ES 3.0."));
5108 return false;
5109 }
5110 break;
5111
5112 case GL_ACTIVE_UNIFORM_BLOCKS:
5113 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5114 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5115 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5116 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5117 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5118 if (context->getClientMajorVersion() < 3)
5119 {
5120 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5121 return false;
5122 }
5123 break;
5124
5125 default:
5126 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5127 return false;
5128 }
5129
5130 return true;
5131}
5132
5133bool ValidateGetProgramivRobustANGLE(Context *context,
5134 GLuint program,
5135 GLenum pname,
5136 GLsizei bufSize,
5137 GLsizei *numParams)
5138{
5139 if (!ValidateRobustEntryPoint(context, bufSize))
5140 {
5141 return false;
5142 }
5143
5144 if (!ValidateGetProgramiv(context, program, pname, numParams))
5145 {
5146 return false;
5147 }
5148
5149 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5150 {
5151 return false;
5152 }
5153
5154 return true;
5155}
5156
Geoff Lang740d9022016-10-07 11:20:52 -04005157bool ValidateGetRenderbufferParameteriv(Context *context,
5158 GLenum target,
5159 GLenum pname,
5160 GLint *params)
5161{
5162 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5163}
5164
5165bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5166 GLenum target,
5167 GLenum pname,
5168 GLsizei bufSize,
5169 GLsizei *length,
5170 GLint *params)
5171{
5172 if (!ValidateRobustEntryPoint(context, bufSize))
5173 {
5174 return false;
5175 }
5176
5177 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5178 {
5179 return false;
5180 }
5181
5182 if (!ValidateRobustBufferSize(context, bufSize, *length))
5183 {
5184 return false;
5185 }
5186
5187 return true;
5188}
5189
Geoff Langd7d0ed32016-10-07 11:33:51 -04005190bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5191{
5192 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5193}
5194
5195bool ValidateGetShaderivRobustANGLE(Context *context,
5196 GLuint shader,
5197 GLenum pname,
5198 GLsizei bufSize,
5199 GLsizei *length,
5200 GLint *params)
5201{
5202 if (!ValidateRobustEntryPoint(context, bufSize))
5203 {
5204 return false;
5205 }
5206
5207 if (!ValidateGetShaderivBase(context, shader, pname, length))
5208 {
5209 return false;
5210 }
5211
5212 if (!ValidateRobustBufferSize(context, bufSize, *length))
5213 {
5214 return false;
5215 }
5216
5217 return true;
5218}
5219
Geoff Langc1984ed2016-10-07 12:41:00 -04005220bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5221{
5222 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5223}
5224
5225bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5226 GLenum target,
5227 GLenum pname,
5228 GLsizei bufSize,
5229 GLsizei *length,
5230 GLfloat *params)
5231{
5232 if (!ValidateRobustEntryPoint(context, bufSize))
5233 {
5234 return false;
5235 }
5236
5237 if (!ValidateGetTexParameterBase(context, target, pname, length))
5238 {
5239 return false;
5240 }
5241
5242 if (!ValidateRobustBufferSize(context, bufSize, *length))
5243 {
5244 return false;
5245 }
5246
5247 return true;
5248}
5249
5250bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5251{
5252 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5253}
5254
5255bool ValidateGetTexParameterivRobustANGLE(Context *context,
5256 GLenum target,
5257 GLenum pname,
5258 GLsizei bufSize,
5259 GLsizei *length,
5260 GLint *params)
5261{
5262 if (!ValidateRobustEntryPoint(context, bufSize))
5263 {
5264 return false;
5265 }
5266
5267 if (!ValidateGetTexParameterBase(context, target, pname, length))
5268 {
5269 return false;
5270 }
5271
5272 if (!ValidateRobustBufferSize(context, bufSize, *length))
5273 {
5274 return false;
5275 }
5276
5277 return true;
5278}
5279
5280bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5281{
5282 return ValidateTexParameterBase(context, target, pname, -1, &param);
5283}
5284
5285bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5286{
5287 return ValidateTexParameterBase(context, target, pname, -1, params);
5288}
5289
5290bool ValidateTexParameterfvRobustANGLE(Context *context,
5291 GLenum target,
5292 GLenum pname,
5293 GLsizei bufSize,
5294 const GLfloat *params)
5295{
5296 if (!ValidateRobustEntryPoint(context, bufSize))
5297 {
5298 return false;
5299 }
5300
5301 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5302}
5303
5304bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5305{
5306 return ValidateTexParameterBase(context, target, pname, -1, &param);
5307}
5308
5309bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5310{
5311 return ValidateTexParameterBase(context, target, pname, -1, params);
5312}
5313
5314bool ValidateTexParameterivRobustANGLE(Context *context,
5315 GLenum target,
5316 GLenum pname,
5317 GLsizei bufSize,
5318 const GLint *params)
5319{
5320 if (!ValidateRobustEntryPoint(context, bufSize))
5321 {
5322 return false;
5323 }
5324
5325 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5326}
5327
5328bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5329{
5330 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5331}
5332
5333bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5334 GLuint sampler,
5335 GLenum pname,
5336 GLuint bufSize,
5337 GLsizei *length,
5338 GLfloat *params)
5339{
5340 if (!ValidateRobustEntryPoint(context, bufSize))
5341 {
5342 return false;
5343 }
5344
5345 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5346 {
5347 return false;
5348 }
5349
5350 if (!ValidateRobustBufferSize(context, bufSize, *length))
5351 {
5352 return false;
5353 }
5354
5355 return true;
5356}
5357
5358bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5359{
5360 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5361}
5362
5363bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5364 GLuint sampler,
5365 GLenum pname,
5366 GLuint bufSize,
5367 GLsizei *length,
5368 GLint *params)
5369{
5370 if (!ValidateRobustEntryPoint(context, bufSize))
5371 {
5372 return false;
5373 }
5374
5375 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5376 {
5377 return false;
5378 }
5379
5380 if (!ValidateRobustBufferSize(context, bufSize, *length))
5381 {
5382 return false;
5383 }
5384
5385 return true;
5386}
5387
5388bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5389{
5390 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5391}
5392
5393bool ValidateSamplerParameterfv(Context *context,
5394 GLuint sampler,
5395 GLenum pname,
5396 const GLfloat *params)
5397{
5398 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5399}
5400
5401bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5402 GLuint sampler,
5403 GLenum pname,
5404 GLsizei bufSize,
5405 const GLfloat *params)
5406{
5407 if (!ValidateRobustEntryPoint(context, bufSize))
5408 {
5409 return false;
5410 }
5411
5412 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5413}
5414
5415bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5416{
5417 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5418}
5419
5420bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5421{
5422 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5423}
5424
5425bool ValidateSamplerParameterivRobustANGLE(Context *context,
5426 GLuint sampler,
5427 GLenum pname,
5428 GLsizei bufSize,
5429 const GLint *params)
5430{
5431 if (!ValidateRobustEntryPoint(context, bufSize))
5432 {
5433 return false;
5434 }
5435
5436 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5437}
5438
Geoff Lang0b031062016-10-13 14:30:04 -04005439bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5440{
5441 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5442}
5443
5444bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5445 GLuint index,
5446 GLenum pname,
5447 GLsizei bufSize,
5448 GLsizei *length,
5449 GLfloat *params)
5450{
5451 if (!ValidateRobustEntryPoint(context, bufSize))
5452 {
5453 return false;
5454 }
5455
5456 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5457 {
5458 return false;
5459 }
5460
5461 if (!ValidateRobustBufferSize(context, bufSize, *length))
5462 {
5463 return false;
5464 }
5465
5466 return true;
5467}
5468
5469bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5470{
5471 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5472}
5473
5474bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5475 GLuint index,
5476 GLenum pname,
5477 GLsizei bufSize,
5478 GLsizei *length,
5479 GLint *params)
5480{
5481 if (!ValidateRobustEntryPoint(context, bufSize))
5482 {
5483 return false;
5484 }
5485
5486 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5487 {
5488 return false;
5489 }
5490
5491 if (!ValidateRobustBufferSize(context, bufSize, *length))
5492 {
5493 return false;
5494 }
5495
5496 return true;
5497}
5498
5499bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5500{
5501 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5502}
5503
5504bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5505 GLuint index,
5506 GLenum pname,
5507 GLsizei bufSize,
5508 GLsizei *length,
5509 void **pointer)
5510{
5511 if (!ValidateRobustEntryPoint(context, bufSize))
5512 {
5513 return false;
5514 }
5515
5516 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5517 {
5518 return false;
5519 }
5520
5521 if (!ValidateRobustBufferSize(context, bufSize, *length))
5522 {
5523 return false;
5524 }
5525
5526 return true;
5527}
5528
5529bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5530{
5531 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5532}
5533
5534bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5535 GLuint index,
5536 GLenum pname,
5537 GLsizei bufSize,
5538 GLsizei *length,
5539 GLint *params)
5540{
5541 if (!ValidateRobustEntryPoint(context, bufSize))
5542 {
5543 return false;
5544 }
5545
5546 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5547 {
5548 return false;
5549 }
5550
5551 if (!ValidateRobustBufferSize(context, bufSize, *length))
5552 {
5553 return false;
5554 }
5555
5556 return true;
5557}
5558
5559bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5560{
5561 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5562}
5563
5564bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5565 GLuint index,
5566 GLenum pname,
5567 GLsizei bufSize,
5568 GLsizei *length,
5569 GLuint *params)
5570{
5571 if (!ValidateRobustEntryPoint(context, bufSize))
5572 {
5573 return false;
5574 }
5575
5576 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5577 {
5578 return false;
5579 }
5580
5581 if (!ValidateRobustBufferSize(context, bufSize, *length))
5582 {
5583 return false;
5584 }
5585
5586 return true;
5587}
5588
Geoff Lang6899b872016-10-14 11:30:13 -04005589bool ValidateGetActiveUniformBlockiv(Context *context,
5590 GLuint program,
5591 GLuint uniformBlockIndex,
5592 GLenum pname,
5593 GLint *params)
5594{
5595 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5596}
5597
5598bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5599 GLuint program,
5600 GLuint uniformBlockIndex,
5601 GLenum pname,
5602 GLsizei bufSize,
5603 GLsizei *length,
5604 GLint *params)
5605{
5606 if (!ValidateRobustEntryPoint(context, bufSize))
5607 {
5608 return false;
5609 }
5610
5611 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5612 {
5613 return false;
5614 }
5615
5616 if (!ValidateRobustBufferSize(context, bufSize, *length))
5617 {
5618 return false;
5619 }
5620
5621 return true;
5622}
5623
Geoff Lang0a9661f2016-10-20 10:59:20 -07005624bool ValidateGetInternalFormativ(Context *context,
5625 GLenum target,
5626 GLenum internalformat,
5627 GLenum pname,
5628 GLsizei bufSize,
5629 GLint *params)
5630{
5631 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5632 nullptr);
5633}
5634
5635bool ValidateGetInternalFormativRobustANGLE(Context *context,
5636 GLenum target,
5637 GLenum internalformat,
5638 GLenum pname,
5639 GLsizei bufSize,
5640 GLsizei *length,
5641 GLint *params)
5642{
5643 if (!ValidateRobustEntryPoint(context, bufSize))
5644 {
5645 return false;
5646 }
5647
5648 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5649 {
5650 return false;
5651 }
5652
5653 if (!ValidateRobustBufferSize(context, bufSize, *length))
5654 {
5655 return false;
5656 }
5657
5658 return true;
5659}
5660
Jamie Madillc29968b2016-01-20 11:17:23 -05005661} // namespace gl