blob: 2297f6fcd1e96de492f07d5e17661badf3e3a2e0 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES2.h"
12#include "libANGLE/validationES3.h"
13#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040014#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Texture.h"
16#include "libANGLE/Framebuffer.h"
17#include "libANGLE/FramebufferAttachment.h"
18#include "libANGLE/formatutils.h"
Geoff Langa8406172015-07-21 16:53:39 -040019#include "libANGLE/Image.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/Query.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050021#include "libANGLE/Program.h"
22#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/TransformFeedback.h"
24#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025
26#include "common/mathutil.h"
27#include "common/utilities.h"
28
Jamie Madille2e406c2016-06-02 13:04:10 -040029using namespace angle;
30
Geoff Lange8ebe7f2013-08-05 15:03:13 -040031namespace gl
32{
Jamie Madille79b1e12015-11-04 16:36:37 -050033const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
34
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Corentin Wallez92db6942016-12-09 13:10:36 -050037bool ValidateDrawAttribs(ValidationContext *context,
38 GLint primcount,
39 GLint maxVertex,
40 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040041{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070042 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040043 const gl::Program *program = state.getProgram();
44
Corentin Wallez327411e2016-12-09 11:09:17 -050045 bool webglCompatibility = context->getExtensions().webglCompatibility;
46
He Yunchaoced53ae2016-11-29 15:00:51 +080047 const VertexArray *vao = state.getVertexArray();
48 const auto &vertexAttribs = vao->getVertexAttributes();
49 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040050 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
51 {
52 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallezfd456442016-12-21 17:57:00 -050053 if (!program->isAttribLocationActive(attributeIndex) || !attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040054 {
Corentin Wallezfd456442016-12-21 17:57:00 -050055 continue;
56 }
Jamie Madill1ca74672015-07-21 15:14:11 -040057
Corentin Wallezfd456442016-12-21 17:57:00 -050058 // If we have no buffer, then we either get an error, or there are no more checks to be done.
59 gl::Buffer *buffer = attrib.buffer.get();
60 if (!buffer)
61 {
62 if (webglCompatibility)
Corentin Wallez327411e2016-12-09 11:09:17 -050063 {
64 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050065 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
66 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
67 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
68 // error.
Corentin Wallez327411e2016-12-09 11:09:17 -050069 context->handleError(
70 Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer."));
Corentin Wallezfd456442016-12-21 17:57:00 -050071 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050072 }
Corentin Wallezfd456442016-12-21 17:57:00 -050073 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040074 {
75 // This is an application error that would normally result in a crash,
76 // but we catch it and return an error
Corentin Wallezfd456442016-12-21 17:57:00 -050077 context->handleError(
78 Error(GL_INVALID_OPERATION,
79 "An enabled vertex array has no buffer and no pointer."));
Jamie Madill1ca74672015-07-21 15:14:11 -040080 return false;
81 }
Corentin Wallezfd456442016-12-21 17:57:00 -050082 continue;
83 }
84
85 // If we're drawing zero vertices, we have enough data.
86 if (vertexCount <= 0 || primcount <= 0)
87 {
88 continue;
89 }
90
91 GLint maxVertexElement = 0;
92 if (attrib.divisor == 0)
93 {
94 maxVertexElement = maxVertex;
95 }
96 else
97 {
98 maxVertexElement = (primcount - 1) / attrib.divisor;
99 }
100
101 // We do manual overflow checks here instead of using safe_math.h because it was
102 // a bottleneck. Thanks to some properties of GL we know inequalities that can
103 // help us make the overflow checks faster.
104
105 // The max possible attribSize is 16 for a vector of 4 32 bit values.
106 constexpr uint64_t kMaxAttribSize = 16;
107 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
108 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
109
110 // We know attribStride is given as a GLsizei which is typedefed to int.
111 // We also know an upper bound for attribSize.
112 static_assert(std::is_same<int, GLsizei>::value, "");
113 uint64_t attribStride = ComputeVertexAttributeStride(attrib);
114 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
115 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
116
117 // Computing the max offset using uint64_t without attrib.offset is overflow
118 // safe. Note: Last vertex element does not take the full stride!
119 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
120 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
121
122 // An overflow can happen when adding the offset, check for it.
123 uint64_t attribOffset = attrib.offset;
124 if (attribDataSizeNoOffset > kUint64Max - attrib.offset)
125 {
126 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
127 return false;
128 }
129 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
130
131 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
132 // We can return INVALID_OPERATION if our vertex attribute does not have
133 // enough backing data.
134 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
135 {
136 context->handleError(Error(GL_INVALID_OPERATION,
137 "Vertex buffer is not big enough for the draw call"));
138 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400139 }
140 }
141
142 return true;
143}
144
Geoff Langf607c602016-09-21 11:46:48 -0400145bool ValidReadPixelsFormatType(ValidationContext *context,
146 GLenum framebufferComponentType,
147 GLenum format,
148 GLenum type)
149{
150 switch (framebufferComponentType)
151 {
152 case GL_UNSIGNED_NORMALIZED:
153 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
154 // ReadPixels with BGRA even if the extension is not present
155 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
156 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
157 type == GL_UNSIGNED_BYTE);
158
159 case GL_SIGNED_NORMALIZED:
160 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
161
162 case GL_INT:
163 return (format == GL_RGBA_INTEGER && type == GL_INT);
164
165 case GL_UNSIGNED_INT:
166 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
167
168 case GL_FLOAT:
169 return (format == GL_RGBA && type == GL_FLOAT);
170
171 default:
172 UNREACHABLE();
173 return false;
174 }
175}
176
Geoff Langf41a7152016-09-19 15:11:17 -0400177bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500178{
179 switch (cap)
180 {
Geoff Langf41a7152016-09-19 15:11:17 -0400181 // EXT_multisample_compatibility
182 case GL_MULTISAMPLE_EXT:
183 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
184 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300185
Geoff Langf41a7152016-09-19 15:11:17 -0400186 case GL_CULL_FACE:
187 case GL_POLYGON_OFFSET_FILL:
188 case GL_SAMPLE_ALPHA_TO_COVERAGE:
189 case GL_SAMPLE_COVERAGE:
190 case GL_SCISSOR_TEST:
191 case GL_STENCIL_TEST:
192 case GL_DEPTH_TEST:
193 case GL_BLEND:
194 case GL_DITHER:
195 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500196
Geoff Langf41a7152016-09-19 15:11:17 -0400197 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
198 case GL_RASTERIZER_DISCARD:
199 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500200
Geoff Langf41a7152016-09-19 15:11:17 -0400201 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
202 case GL_DEBUG_OUTPUT:
203 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500204
Geoff Langf41a7152016-09-19 15:11:17 -0400205 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
206 return queryOnly && context->getExtensions().bindGeneratesResource;
207
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700208 case GL_FRAMEBUFFER_SRGB_EXT:
209 return context->getExtensions().sRGBWriteControl;
210
Geoff Lang3b573612016-10-31 14:08:10 -0400211 case GL_SAMPLE_MASK:
Geoff Lang3b573612016-10-31 14:08:10 -0400212 return context->getClientVersion() >= Version(3, 1);
213
Geoff Langf41a7152016-09-19 15:11:17 -0400214 default:
215 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500216 }
217}
218
Geoff Lang62fce5b2016-09-30 10:46:35 -0400219bool ValidateReadPixelsBase(ValidationContext *context,
220 GLint x,
221 GLint y,
222 GLsizei width,
223 GLsizei height,
224 GLenum format,
225 GLenum type,
226 GLsizei bufSize,
227 GLsizei *length,
228 GLvoid *pixels)
229{
230 if (length != nullptr)
231 {
232 *length = 0;
233 }
234
235 if (width < 0 || height < 0)
236 {
237 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
238 return false;
239 }
240
241 auto readFramebuffer = context->getGLState().getReadFramebuffer();
242
243 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
244 {
245 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
246 return false;
247 }
248
249 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
250 {
251 context->handleError(Error(GL_INVALID_OPERATION));
252 return false;
253 }
254
255 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
256 ASSERT(framebuffer);
257
258 if (framebuffer->getReadBufferState() == GL_NONE)
259 {
260 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
261 return false;
262 }
263
264 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500265 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
266 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
267 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
268 // situation is an application error that would lead to a crash in ANGLE.
269 if (readBuffer == nullptr)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400270 {
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500271 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
Geoff Lang62fce5b2016-09-30 10:46:35 -0400272 return false;
273 }
274
275 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
276 GLenum currentType = framebuffer->getImplementationColorReadType();
277 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
278
279 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
280 bool validFormatTypeCombination =
281 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
282
283 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
284 {
285 context->handleError(Error(GL_INVALID_OPERATION));
286 return false;
287 }
288
289 // Check for pixel pack buffer related API errors
290 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
291 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
292 {
293 // ...the buffer object's data store is currently mapped.
294 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
295 return false;
296 }
297
298 // .. the data would be packed to the buffer object such that the memory writes required
299 // would exceed the data store size.
300 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
301 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
302 const gl::Extents size(width, height, 1);
303 const auto &pack = context->getGLState().getPackState();
304
305 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
306 if (endByteOrErr.isError())
307 {
308 context->handleError(endByteOrErr.getError());
309 return false;
310 }
311
312 size_t endByte = endByteOrErr.getResult();
313 if (bufSize >= 0)
314 {
315
316 if (static_cast<size_t>(bufSize) < endByte)
317 {
318 context->handleError(
319 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
320 return false;
321 }
322 }
323
324 if (pixelPackBuffer != nullptr)
325 {
326 CheckedNumeric<size_t> checkedEndByte(endByte);
327 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
328 checkedEndByte += checkedOffset;
329
330 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
331 {
332 // Overflow past the end of the buffer
333 context->handleError(
334 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
335 return false;
336 }
337 }
338
339 if (length != nullptr)
340 {
341 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
342 {
343 context->handleError(
344 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
345 return false;
346 }
347
348 *length = static_cast<GLsizei>(endByte);
349 }
350
351 return true;
352}
353
Geoff Lang740d9022016-10-07 11:20:52 -0400354bool ValidateGetRenderbufferParameterivBase(Context *context,
355 GLenum target,
356 GLenum pname,
357 GLsizei *length)
358{
359 if (length)
360 {
361 *length = 0;
362 }
363
364 if (target != GL_RENDERBUFFER)
365 {
366 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
367 return false;
368 }
369
370 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
371 if (renderbuffer == nullptr)
372 {
373 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
374 return false;
375 }
376
377 switch (pname)
378 {
379 case GL_RENDERBUFFER_WIDTH:
380 case GL_RENDERBUFFER_HEIGHT:
381 case GL_RENDERBUFFER_INTERNAL_FORMAT:
382 case GL_RENDERBUFFER_RED_SIZE:
383 case GL_RENDERBUFFER_GREEN_SIZE:
384 case GL_RENDERBUFFER_BLUE_SIZE:
385 case GL_RENDERBUFFER_ALPHA_SIZE:
386 case GL_RENDERBUFFER_DEPTH_SIZE:
387 case GL_RENDERBUFFER_STENCIL_SIZE:
388 break;
389
390 case GL_RENDERBUFFER_SAMPLES_ANGLE:
391 if (!context->getExtensions().framebufferMultisample)
392 {
393 context->handleError(
394 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
395 return false;
396 }
397 break;
398
399 default:
400 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
401 return false;
402 }
403
404 if (length)
405 {
406 *length = 1;
407 }
408 return true;
409}
410
Geoff Langd7d0ed32016-10-07 11:33:51 -0400411bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
412{
413 if (length)
414 {
415 *length = 0;
416 }
417
418 if (GetValidShader(context, shader) == nullptr)
419 {
420 return false;
421 }
422
423 switch (pname)
424 {
425 case GL_SHADER_TYPE:
426 case GL_DELETE_STATUS:
427 case GL_COMPILE_STATUS:
428 case GL_INFO_LOG_LENGTH:
429 case GL_SHADER_SOURCE_LENGTH:
430 break;
431
432 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
433 if (!context->getExtensions().translatedShaderSource)
434 {
435 context->handleError(
436 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
437 return false;
438 }
439 break;
440
441 default:
442 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
443 return false;
444 }
445
446 if (length)
447 {
448 *length = 1;
449 }
450 return true;
451}
452
Geoff Langc1984ed2016-10-07 12:41:00 -0400453bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
454{
455 if (length)
456 {
457 *length = 0;
458 }
459
460 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
461 {
462 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
463 return false;
464 }
465
466 if (context->getTargetTexture(target) == nullptr)
467 {
468 // Should only be possible for external textures
469 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
470 return false;
471 }
472
473 switch (pname)
474 {
475 case GL_TEXTURE_MAG_FILTER:
476 case GL_TEXTURE_MIN_FILTER:
477 case GL_TEXTURE_WRAP_S:
478 case GL_TEXTURE_WRAP_T:
479 break;
480
481 case GL_TEXTURE_USAGE_ANGLE:
482 if (!context->getExtensions().textureUsage)
483 {
484 context->handleError(
485 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
486 return false;
487 }
488 break;
489
490 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
491 if (!context->getExtensions().textureFilterAnisotropic)
492 {
493 context->handleError(
494 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
495 return false;
496 }
497 break;
498
499 case GL_TEXTURE_IMMUTABLE_FORMAT:
500 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
501 {
502 context->handleError(
503 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
504 return false;
505 }
506 break;
507
508 case GL_TEXTURE_WRAP_R:
509 case GL_TEXTURE_IMMUTABLE_LEVELS:
510 case GL_TEXTURE_SWIZZLE_R:
511 case GL_TEXTURE_SWIZZLE_G:
512 case GL_TEXTURE_SWIZZLE_B:
513 case GL_TEXTURE_SWIZZLE_A:
514 case GL_TEXTURE_BASE_LEVEL:
515 case GL_TEXTURE_MAX_LEVEL:
516 case GL_TEXTURE_MIN_LOD:
517 case GL_TEXTURE_MAX_LOD:
518 case GL_TEXTURE_COMPARE_MODE:
519 case GL_TEXTURE_COMPARE_FUNC:
520 if (context->getClientMajorVersion() < 3)
521 {
522 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
523 return false;
524 }
525 break;
526
Geoff Lang81c6b572016-10-19 14:07:52 -0700527 case GL_TEXTURE_SRGB_DECODE_EXT:
528 if (!context->getExtensions().textureSRGBDecode)
529 {
530 context->handleError(
531 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
532 return false;
533 }
534 break;
535
Geoff Langc1984ed2016-10-07 12:41:00 -0400536 default:
537 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
538 return false;
539 }
540
541 if (length)
542 {
543 *length = 1;
544 }
545 return true;
546}
547
548template <typename ParamType>
549bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
550{
551 switch (ConvertToGLenum(params[0]))
552 {
553 case GL_CLAMP_TO_EDGE:
554 break;
555
556 case GL_REPEAT:
557 case GL_MIRRORED_REPEAT:
558 if (isExternalTextureTarget)
559 {
560 // OES_EGL_image_external specifies this error.
561 context->handleError(Error(
562 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
563 return false;
564 }
565 break;
566
567 default:
568 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
569 return false;
570 }
571
572 return true;
573}
574
575template <typename ParamType>
576bool ValidateTextureMinFilterValue(Context *context,
577 ParamType *params,
578 bool isExternalTextureTarget)
579{
580 switch (ConvertToGLenum(params[0]))
581 {
582 case GL_NEAREST:
583 case GL_LINEAR:
584 break;
585
586 case GL_NEAREST_MIPMAP_NEAREST:
587 case GL_LINEAR_MIPMAP_NEAREST:
588 case GL_NEAREST_MIPMAP_LINEAR:
589 case GL_LINEAR_MIPMAP_LINEAR:
590 if (isExternalTextureTarget)
591 {
592 // OES_EGL_image_external specifies this error.
593 context->handleError(
594 Error(GL_INVALID_ENUM,
595 "external textures only support NEAREST and LINEAR filtering"));
596 return false;
597 }
598 break;
599
600 default:
601 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
602 return false;
603 }
604
605 return true;
606}
607
608template <typename ParamType>
609bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
610{
611 switch (ConvertToGLenum(params[0]))
612 {
613 case GL_NEAREST:
614 case GL_LINEAR:
615 break;
616
617 default:
618 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
619 return false;
620 }
621
622 return true;
623}
624
625template <typename ParamType>
626bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
627{
628 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
629 switch (ConvertToGLenum(params[0]))
630 {
631 case GL_NONE:
632 case GL_COMPARE_REF_TO_TEXTURE:
633 break;
634
635 default:
636 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
637 return false;
638 }
639
640 return true;
641}
642
643template <typename ParamType>
644bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
645{
646 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
647 switch (ConvertToGLenum(params[0]))
648 {
649 case GL_LEQUAL:
650 case GL_GEQUAL:
651 case GL_LESS:
652 case GL_GREATER:
653 case GL_EQUAL:
654 case GL_NOTEQUAL:
655 case GL_ALWAYS:
656 case GL_NEVER:
657 break;
658
659 default:
660 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
661 return false;
662 }
663
664 return true;
665}
666
667template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700668bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
669{
670 if (!context->getExtensions().textureSRGBDecode)
671 {
672 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
673 return false;
674 }
675
676 switch (ConvertToGLenum(params[0]))
677 {
678 case GL_DECODE_EXT:
679 case GL_SKIP_DECODE_EXT:
680 break;
681
682 default:
683 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
684 return false;
685 }
686
687 return true;
688}
689
690template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400691bool ValidateTexParameterBase(Context *context,
692 GLenum target,
693 GLenum pname,
694 GLsizei bufSize,
695 ParamType *params)
696{
697 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
698 {
699 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
700 return false;
701 }
702
703 if (context->getTargetTexture(target) == nullptr)
704 {
705 // Should only be possible for external textures
706 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
707 return false;
708 }
709
710 const GLsizei minBufSize = 1;
711 if (bufSize >= 0 && bufSize < minBufSize)
712 {
713 context->handleError(
714 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
715 return false;
716 }
717
718 switch (pname)
719 {
720 case GL_TEXTURE_WRAP_R:
721 case GL_TEXTURE_SWIZZLE_R:
722 case GL_TEXTURE_SWIZZLE_G:
723 case GL_TEXTURE_SWIZZLE_B:
724 case GL_TEXTURE_SWIZZLE_A:
725 case GL_TEXTURE_BASE_LEVEL:
726 case GL_TEXTURE_MAX_LEVEL:
727 case GL_TEXTURE_COMPARE_MODE:
728 case GL_TEXTURE_COMPARE_FUNC:
729 case GL_TEXTURE_MIN_LOD:
730 case GL_TEXTURE_MAX_LOD:
731 if (context->getClientMajorVersion() < 3)
732 {
733 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
734 return false;
735 }
736 if (target == GL_TEXTURE_EXTERNAL_OES &&
737 !context->getExtensions().eglImageExternalEssl3)
738 {
739 context->handleError(Error(GL_INVALID_ENUM,
740 "ES3 texture parameters are not available without "
741 "GL_OES_EGL_image_external_essl3."));
742 return false;
743 }
744 break;
745
746 default:
747 break;
748 }
749
750 switch (pname)
751 {
752 case GL_TEXTURE_WRAP_S:
753 case GL_TEXTURE_WRAP_T:
754 case GL_TEXTURE_WRAP_R:
755 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
756 {
757 return false;
758 }
759 break;
760
761 case GL_TEXTURE_MIN_FILTER:
762 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
763 {
764 return false;
765 }
766 break;
767
768 case GL_TEXTURE_MAG_FILTER:
769 if (!ValidateTextureMagFilterValue(context, params))
770 {
771 return false;
772 }
773 break;
774
775 case GL_TEXTURE_USAGE_ANGLE:
776 switch (ConvertToGLenum(params[0]))
777 {
778 case GL_NONE:
779 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
780 break;
781
782 default:
783 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
784 return false;
785 }
786 break;
787
788 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
789 if (!context->getExtensions().textureFilterAnisotropic)
790 {
791 context->handleError(
792 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
793 return false;
794 }
795
796 // we assume the parameter passed to this validation method is truncated, not rounded
797 if (params[0] < 1)
798 {
799 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
800 return false;
801 }
802 break;
803
804 case GL_TEXTURE_MIN_LOD:
805 case GL_TEXTURE_MAX_LOD:
806 // any value is permissible
807 break;
808
809 case GL_TEXTURE_COMPARE_MODE:
810 if (!ValidateTextureCompareModeValue(context, params))
811 {
812 return false;
813 }
814 break;
815
816 case GL_TEXTURE_COMPARE_FUNC:
817 if (!ValidateTextureCompareFuncValue(context, params))
818 {
819 return false;
820 }
821 break;
822
823 case GL_TEXTURE_SWIZZLE_R:
824 case GL_TEXTURE_SWIZZLE_G:
825 case GL_TEXTURE_SWIZZLE_B:
826 case GL_TEXTURE_SWIZZLE_A:
827 switch (ConvertToGLenum(params[0]))
828 {
829 case GL_RED:
830 case GL_GREEN:
831 case GL_BLUE:
832 case GL_ALPHA:
833 case GL_ZERO:
834 case GL_ONE:
835 break;
836
837 default:
838 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
839 return false;
840 }
841 break;
842
843 case GL_TEXTURE_BASE_LEVEL:
844 if (params[0] < 0)
845 {
846 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
847 return false;
848 }
849 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
850 {
851 context->handleError(
852 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
853 return false;
854 }
855 break;
856
857 case GL_TEXTURE_MAX_LEVEL:
858 if (params[0] < 0)
859 {
860 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
861 return false;
862 }
863 break;
864
Geoff Lang3b573612016-10-31 14:08:10 -0400865 case GL_DEPTH_STENCIL_TEXTURE_MODE:
866 if (context->getClientVersion() < Version(3, 1))
867 {
868 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
869 return false;
870 }
Geoff Lang9f090372016-12-02 10:20:43 -0500871 switch (ConvertToGLenum(params[0]))
872 {
873 case GL_DEPTH_COMPONENT:
874 case GL_STENCIL_INDEX:
875 break;
876
877 default:
878 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
879 return false;
880 }
Geoff Lang3b573612016-10-31 14:08:10 -0400881 break;
882
Geoff Lang81c6b572016-10-19 14:07:52 -0700883 case GL_TEXTURE_SRGB_DECODE_EXT:
884 if (!ValidateTextureSRGBDecodeValue(context, params))
885 {
886 return false;
887 }
888 break;
889
Geoff Langc1984ed2016-10-07 12:41:00 -0400890 default:
891 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
892 return false;
893 }
894
895 return true;
896}
897
898template <typename ParamType>
899bool ValidateSamplerParameterBase(Context *context,
900 GLuint sampler,
901 GLenum pname,
902 GLsizei bufSize,
903 ParamType *params)
904{
905 if (context->getClientMajorVersion() < 3)
906 {
907 context->handleError(
908 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
909 return false;
910 }
911
912 if (!context->isSampler(sampler))
913 {
914 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
915 return false;
916 }
917
918 const GLsizei minBufSize = 1;
919 if (bufSize >= 0 && bufSize < minBufSize)
920 {
921 context->handleError(
922 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
923 return false;
924 }
925
926 switch (pname)
927 {
928 case GL_TEXTURE_WRAP_S:
929 case GL_TEXTURE_WRAP_T:
930 case GL_TEXTURE_WRAP_R:
931 if (!ValidateTextureWrapModeValue(context, params, false))
932 {
933 return false;
934 }
935 break;
936
937 case GL_TEXTURE_MIN_FILTER:
938 if (!ValidateTextureMinFilterValue(context, params, false))
939 {
940 return false;
941 }
942 break;
943
944 case GL_TEXTURE_MAG_FILTER:
945 if (!ValidateTextureMagFilterValue(context, params))
946 {
947 return false;
948 }
949 break;
950
951 case GL_TEXTURE_MIN_LOD:
952 case GL_TEXTURE_MAX_LOD:
953 // any value is permissible
954 break;
955
956 case GL_TEXTURE_COMPARE_MODE:
957 if (!ValidateTextureCompareModeValue(context, params))
958 {
959 return false;
960 }
961 break;
962
963 case GL_TEXTURE_COMPARE_FUNC:
964 if (!ValidateTextureCompareFuncValue(context, params))
965 {
966 return false;
967 }
968 break;
969
Geoff Lang81c6b572016-10-19 14:07:52 -0700970 case GL_TEXTURE_SRGB_DECODE_EXT:
971 if (!ValidateTextureSRGBDecodeValue(context, params))
972 {
973 return false;
974 }
975 break;
976
Geoff Langc1984ed2016-10-07 12:41:00 -0400977 default:
978 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
979 return false;
980 }
981
982 return true;
983}
984
985bool ValidateGetSamplerParameterBase(Context *context,
986 GLuint sampler,
987 GLenum pname,
988 GLsizei *length)
989{
990 if (length)
991 {
992 *length = 0;
993 }
994
995 if (context->getClientMajorVersion() < 3)
996 {
997 context->handleError(
998 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
999 return false;
1000 }
1001
1002 if (!context->isSampler(sampler))
1003 {
1004 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
1005 return false;
1006 }
1007
1008 switch (pname)
1009 {
1010 case GL_TEXTURE_WRAP_S:
1011 case GL_TEXTURE_WRAP_T:
1012 case GL_TEXTURE_WRAP_R:
1013 case GL_TEXTURE_MIN_FILTER:
1014 case GL_TEXTURE_MAG_FILTER:
1015 case GL_TEXTURE_MIN_LOD:
1016 case GL_TEXTURE_MAX_LOD:
1017 case GL_TEXTURE_COMPARE_MODE:
1018 case GL_TEXTURE_COMPARE_FUNC:
1019 break;
1020
Geoff Lang81c6b572016-10-19 14:07:52 -07001021 case GL_TEXTURE_SRGB_DECODE_EXT:
1022 if (!context->getExtensions().textureSRGBDecode)
1023 {
1024 context->handleError(
1025 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
1026 return false;
1027 }
1028 break;
1029
Geoff Langc1984ed2016-10-07 12:41:00 -04001030 default:
1031 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1032 return false;
1033 }
1034
1035 if (length)
1036 {
1037 *length = 1;
1038 }
1039 return true;
1040}
1041
Geoff Lang0b031062016-10-13 14:30:04 -04001042bool ValidateGetVertexAttribBase(Context *context,
1043 GLuint index,
1044 GLenum pname,
1045 GLsizei *length,
1046 bool pointer,
1047 bool pureIntegerEntryPoint)
1048{
1049 if (length)
1050 {
1051 *length = 0;
1052 }
1053
1054 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1055 {
1056 context->handleError(
1057 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1058 return false;
1059 }
1060
1061 if (index >= context->getCaps().maxVertexAttributes)
1062 {
1063 context->handleError(Error(
1064 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1065 return false;
1066 }
1067
1068 if (pointer)
1069 {
1070 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1071 {
1072 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1073 return false;
1074 }
1075 }
1076 else
1077 {
1078 switch (pname)
1079 {
1080 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1081 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1082 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1083 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1084 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1085 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1086 case GL_CURRENT_VERTEX_ATTRIB:
1087 break;
1088
1089 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1090 static_assert(
1091 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1092 "ANGLE extension enums not equal to GL enums.");
1093 if (context->getClientMajorVersion() < 3 &&
1094 !context->getExtensions().instancedArrays)
1095 {
1096 context->handleError(Error(GL_INVALID_ENUM,
1097 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1098 "3.0 or GL_ANGLE_instanced_arrays."));
1099 return false;
1100 }
1101 break;
1102
1103 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1104 if (context->getClientMajorVersion() < 3)
1105 {
1106 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1107 return false;
1108 }
1109 break;
1110
1111 default:
1112 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1113 return false;
1114 }
1115 }
1116
1117 if (length)
1118 {
1119 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1120 {
1121 *length = 4;
1122 }
1123 else
1124 {
1125 *length = 1;
1126 }
1127 }
1128
1129 return true;
1130}
1131
Geoff Lang6899b872016-10-14 11:30:13 -04001132bool ValidateGetActiveUniformBlockivBase(Context *context,
1133 GLuint program,
1134 GLuint uniformBlockIndex,
1135 GLenum pname,
1136 GLsizei *length)
1137{
1138 if (length)
1139 {
1140 *length = 0;
1141 }
1142
1143 if (context->getClientMajorVersion() < 3)
1144 {
1145 context->handleError(
1146 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1147 return false;
1148 }
1149
1150 Program *programObject = GetValidProgram(context, program);
1151 if (!programObject)
1152 {
1153 return false;
1154 }
1155
1156 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1157 {
1158 context->handleError(
1159 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1160 return false;
1161 }
1162
1163 switch (pname)
1164 {
1165 case GL_UNIFORM_BLOCK_BINDING:
1166 case GL_UNIFORM_BLOCK_DATA_SIZE:
1167 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1168 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1169 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1170 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1171 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1172 break;
1173
1174 default:
1175 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1176 return false;
1177 }
1178
1179 if (length)
1180 {
1181 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1182 {
1183 const UniformBlock &uniformBlock =
1184 programObject->getUniformBlockByIndex(uniformBlockIndex);
1185 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1186 }
1187 else
1188 {
1189 *length = 1;
1190 }
1191 }
1192
1193 return true;
1194}
1195
Geoff Langebebe1c2016-10-14 12:01:31 -04001196bool ValidateGetBufferParameterBase(ValidationContext *context,
1197 GLenum target,
1198 GLenum pname,
1199 bool pointerVersion,
1200 GLsizei *numParams)
1201{
1202 if (numParams)
1203 {
1204 *numParams = 0;
1205 }
1206
1207 if (!ValidBufferTarget(context, target))
1208 {
1209 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1210 return false;
1211 }
1212
1213 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1214 if (!buffer)
1215 {
1216 // A null buffer means that "0" is bound to the requested buffer target
1217 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1218 return false;
1219 }
1220
1221 const Extensions &extensions = context->getExtensions();
1222
1223 switch (pname)
1224 {
1225 case GL_BUFFER_USAGE:
1226 case GL_BUFFER_SIZE:
1227 break;
1228
1229 case GL_BUFFER_ACCESS_OES:
1230 if (!extensions.mapBuffer)
1231 {
1232 context->handleError(
Jamie Madillcc6ac252017-01-25 12:57:21 -08001233 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001234 return false;
1235 }
1236 break;
1237
1238 case GL_BUFFER_MAPPED:
1239 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1240 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1241 !extensions.mapBufferRange)
1242 {
1243 context->handleError(Error(
1244 GL_INVALID_ENUM,
Jamie Madillcc6ac252017-01-25 12:57:21 -08001245 "pname requires OpenGL ES 3.0, GL_OES_mapbuffer or GL_EXT_map_buffer_range."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001246 return false;
1247 }
1248 break;
1249
1250 case GL_BUFFER_MAP_POINTER:
1251 if (!pointerVersion)
1252 {
1253 context->handleError(
1254 Error(GL_INVALID_ENUM,
1255 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1256 return false;
1257 }
1258 break;
1259
1260 case GL_BUFFER_ACCESS_FLAGS:
1261 case GL_BUFFER_MAP_OFFSET:
1262 case GL_BUFFER_MAP_LENGTH:
1263 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1264 {
1265 context->handleError(Error(
1266 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1267 return false;
1268 }
1269 break;
1270
1271 default:
1272 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1273 return false;
1274 }
1275
1276 // All buffer parameter queries return one value.
1277 if (numParams)
1278 {
1279 *numParams = 1;
1280 }
1281
1282 return true;
1283}
1284
Geoff Lang0a9661f2016-10-20 10:59:20 -07001285bool ValidateGetInternalFormativBase(Context *context,
1286 GLenum target,
1287 GLenum internalformat,
1288 GLenum pname,
1289 GLsizei bufSize,
1290 GLsizei *numParams)
1291{
1292 if (numParams)
1293 {
1294 *numParams = 0;
1295 }
1296
1297 if (context->getClientMajorVersion() < 3)
1298 {
1299 context->handleError(
1300 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1301 return false;
1302 }
1303
1304 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1305 if (!formatCaps.renderable)
1306 {
1307 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1308 return false;
1309 }
1310
1311 switch (target)
1312 {
1313 case GL_RENDERBUFFER:
1314 break;
1315
JiangYizhoubddc46b2016-12-09 09:50:51 +08001316 case GL_TEXTURE_2D_MULTISAMPLE:
1317 if (context->getClientVersion() < ES_3_1)
1318 {
1319 context->handleError(
1320 Error(GL_INVALID_OPERATION, "Texture target requires at least OpenGL ES 3.1."));
1321 return false;
1322 }
1323 break;
1324
Geoff Lang0a9661f2016-10-20 10:59:20 -07001325 default:
1326 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1327 return false;
1328 }
1329
1330 if (bufSize < 0)
1331 {
1332 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1333 return false;
1334 }
1335
1336 GLsizei maxWriteParams = 0;
1337 switch (pname)
1338 {
1339 case GL_NUM_SAMPLE_COUNTS:
1340 maxWriteParams = 1;
1341 break;
1342
1343 case GL_SAMPLES:
1344 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1345 break;
1346
1347 default:
1348 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1349 return false;
1350 }
1351
1352 if (numParams)
1353 {
1354 // glGetInternalFormativ will not overflow bufSize
1355 *numParams = std::min(bufSize, maxWriteParams);
1356 }
1357
1358 return true;
1359}
1360
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001361bool ValidateUniformCommonBase(gl::Context *context,
1362 gl::Program *program,
1363 GLint location,
1364 GLsizei count,
1365 const LinkedUniform **uniformOut)
1366{
1367 // TODO(Jiajia): Add image uniform check in future.
1368 if (count < 0)
1369 {
1370 context->handleError(Error(GL_INVALID_VALUE));
1371 return false;
1372 }
1373
1374 if (!program || !program->isLinked())
1375 {
1376 context->handleError(Error(GL_INVALID_OPERATION));
1377 return false;
1378 }
1379
1380 if (location == -1)
1381 {
1382 // Silently ignore the uniform command
1383 return false;
1384 }
1385
1386 const auto &uniformLocations = program->getUniformLocations();
1387 size_t castedLocation = static_cast<size_t>(location);
1388 if (castedLocation >= uniformLocations.size())
1389 {
1390 context->handleError(Error(GL_INVALID_OPERATION, "Invalid uniform location"));
1391 return false;
1392 }
1393
1394 const auto &uniformLocation = uniformLocations[castedLocation];
1395 if (uniformLocation.ignored)
1396 {
1397 // Silently ignore the uniform command
1398 return false;
1399 }
1400
1401 if (!uniformLocation.used)
1402 {
1403 context->handleError(Error(GL_INVALID_OPERATION));
1404 return false;
1405 }
1406
1407 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
1408
1409 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
1410 if (!uniform.isArray() && count > 1)
1411 {
1412 context->handleError(Error(GL_INVALID_OPERATION));
1413 return false;
1414 }
1415
1416 *uniformOut = &uniform;
1417 return true;
1418}
1419
Frank Henigman999b0fd2017-02-02 21:45:55 -05001420bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -05001421 GLenum uniformType,
1422 GLsizei count,
1423 const GLint *value)
1424{
1425 // Value type is GL_INT, because we only get here from glUniform1i{v}.
1426 // It is compatible with INT or BOOL.
1427 // Do these cheap tests first, for a little extra speed.
1428 if (GL_INT == uniformType || GL_BOOL == uniformType)
1429 {
1430 return true;
1431 }
1432
1433 if (IsSamplerType(uniformType))
1434 {
Frank Henigman999b0fd2017-02-02 21:45:55 -05001435 // Check that the values are in range.
1436 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
1437 for (GLsizei i = 0; i < count; ++i)
1438 {
1439 if (value[i] < 0 || value[i] >= max)
1440 {
1441 context->handleError(Error(GL_INVALID_VALUE, "sampler uniform value out of range"));
1442 return false;
1443 }
1444 }
Frank Henigmana98a6472017-02-02 21:38:32 -05001445 return true;
1446 }
1447
1448 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1449 return false;
1450}
1451
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001452bool ValidateUniformValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1453{
1454 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -05001455 // Do the cheaper test first, for a little extra speed.
1456 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001457 {
1458 return true;
1459 }
1460
1461 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1462 return false;
1463}
1464
1465bool ValidateUniformMatrixValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1466{
1467 // Check that the value type is compatible with uniform type.
1468 if (valueType == uniformType)
1469 {
1470 return true;
1471 }
1472
1473 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1474 return false;
1475}
1476
Geoff Langf41a7152016-09-19 15:11:17 -04001477} // anonymous namespace
1478
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001479bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001480{
Jamie Madilld7460c72014-01-21 16:38:14 -05001481 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001482 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001483 case GL_TEXTURE_2D:
1484 case GL_TEXTURE_CUBE_MAP:
1485 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001486
He Yunchaoced53ae2016-11-29 15:00:51 +08001487 case GL_TEXTURE_3D:
1488 case GL_TEXTURE_2D_ARRAY:
1489 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001490
He Yunchaoced53ae2016-11-29 15:00:51 +08001491 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001492 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001493
He Yunchaoced53ae2016-11-29 15:00:51 +08001494 default:
1495 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001496 }
Jamie Madill35d15012013-10-07 10:46:37 -04001497}
1498
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001499bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1500{
1501 switch (target)
1502 {
1503 case GL_TEXTURE_2D:
1504 case GL_TEXTURE_CUBE_MAP:
1505 return true;
1506
1507 default:
1508 return false;
1509 }
1510}
1511
1512bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1513{
1514 switch (target)
1515 {
1516 case GL_TEXTURE_3D:
1517 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001518 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001519
1520 default:
1521 return false;
1522 }
1523}
1524
Ian Ewellbda75592016-04-18 17:25:54 -04001525// Most texture GL calls are not compatible with external textures, so we have a separate validation
1526// function for use in the GL calls that do
1527bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1528{
1529 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1530 (context->getExtensions().eglImageExternal ||
1531 context->getExtensions().eglStreamConsumerExternal);
1532}
1533
Shannon Woods4dfed832014-03-17 20:03:39 -04001534// This function differs from ValidTextureTarget in that the target must be
1535// usable as the destination of a 2D operation-- so a cube face is valid, but
1536// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001537// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001538bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001539{
1540 switch (target)
1541 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001542 case GL_TEXTURE_2D:
1543 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1544 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1545 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1546 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1547 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1548 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1549 return true;
1550 default:
1551 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001552 }
1553}
1554
1555bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1556{
1557 switch (target)
1558 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001559 case GL_TEXTURE_3D:
1560 case GL_TEXTURE_2D_ARRAY:
1561 return true;
1562 default:
1563 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001564 }
1565}
1566
He Yunchao11b038b2016-11-22 21:24:04 +08001567bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1568{
1569 switch (target)
1570 {
1571 case GL_TEXTURE_2D:
1572 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1573 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1574 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1575 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1576 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1577 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1578 case GL_TEXTURE_3D:
1579 case GL_TEXTURE_2D_ARRAY:
1580 case GL_TEXTURE_2D_MULTISAMPLE:
1581 return true;
1582 default:
1583 return false;
1584 }
1585}
1586
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001587bool ValidFramebufferTarget(GLenum target)
1588{
He Yunchaoced53ae2016-11-29 15:00:51 +08001589 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1590 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001591 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001592
1593 switch (target)
1594 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001595 case GL_FRAMEBUFFER:
1596 return true;
1597 case GL_READ_FRAMEBUFFER:
1598 return true;
1599 case GL_DRAW_FRAMEBUFFER:
1600 return true;
1601 default:
1602 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001603 }
1604}
1605
Jamie Madill29639852016-09-02 15:00:09 -04001606bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001607{
1608 switch (target)
1609 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001610 case GL_ARRAY_BUFFER:
1611 case GL_ELEMENT_ARRAY_BUFFER:
1612 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001613
He Yunchaoced53ae2016-11-29 15:00:51 +08001614 case GL_PIXEL_PACK_BUFFER:
1615 case GL_PIXEL_UNPACK_BUFFER:
1616 return (context->getExtensions().pixelBufferObject ||
1617 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001618
He Yunchaoced53ae2016-11-29 15:00:51 +08001619 case GL_COPY_READ_BUFFER:
1620 case GL_COPY_WRITE_BUFFER:
1621 case GL_TRANSFORM_FEEDBACK_BUFFER:
1622 case GL_UNIFORM_BUFFER:
1623 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001624
He Yunchaoced53ae2016-11-29 15:00:51 +08001625 case GL_ATOMIC_COUNTER_BUFFER:
1626 case GL_SHADER_STORAGE_BUFFER:
1627 case GL_DRAW_INDIRECT_BUFFER:
1628 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001629 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001630
He Yunchaoced53ae2016-11-29 15:00:51 +08001631 default:
1632 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001633 }
1634}
1635
Jamie Madillc29968b2016-01-20 11:17:23 -05001636bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001637{
Jamie Madillc29968b2016-01-20 11:17:23 -05001638 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001639 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001640 switch (target)
1641 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001642 case GL_TEXTURE_2D:
1643 maxDimension = caps.max2DTextureSize;
1644 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001645 case GL_TEXTURE_CUBE_MAP:
1646 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1647 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1648 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1649 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1650 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1651 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1652 maxDimension = caps.maxCubeMapTextureSize;
1653 break;
1654 case GL_TEXTURE_3D:
1655 maxDimension = caps.max3DTextureSize;
1656 break;
1657 case GL_TEXTURE_2D_ARRAY:
1658 maxDimension = caps.max2DTextureSize;
1659 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001660 case GL_TEXTURE_2D_MULTISAMPLE:
1661 maxDimension = caps.max2DTextureSize;
1662 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001663 default:
1664 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001665 }
1666
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001667 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001668}
1669
Geoff Langcc507aa2016-12-12 10:09:52 -05001670bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001671 GLenum target,
1672 GLint level,
1673 GLsizei width,
1674 GLsizei height,
1675 GLsizei depth,
1676 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001677{
1678 if (level < 0 || width < 0 || height < 0 || depth < 0)
1679 {
1680 return false;
1681 }
1682
Austin Kinross08528e12015-10-07 16:24:40 -07001683 // TexSubImage parameters can be NPOT without textureNPOT extension,
1684 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001685 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001686 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001687 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001688 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001689 {
1690 return false;
1691 }
1692
1693 if (!ValidMipLevel(context, target, level))
1694 {
1695 return false;
1696 }
1697
1698 return true;
1699}
1700
Geoff Lang0d8b7242015-09-09 14:56:53 -04001701bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1702{
1703 // List of compressed format that require that the texture size is smaller than or a multiple of
1704 // the compressed block size.
1705 switch (internalFormat)
1706 {
1707 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1708 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1709 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1710 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001711 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001712 return true;
1713
1714 default:
1715 return false;
1716 }
1717}
1718
Jamie Madillc29968b2016-01-20 11:17:23 -05001719bool ValidCompressedImageSize(const ValidationContext *context,
1720 GLenum internalFormat,
1721 GLsizei width,
1722 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001723{
Geoff Lang5d601382014-07-22 15:14:06 -04001724 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1725 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001726 {
1727 return false;
1728 }
1729
Geoff Lang0d8b7242015-09-09 14:56:53 -04001730 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001731 {
1732 return false;
1733 }
1734
Geoff Lang0d8b7242015-09-09 14:56:53 -04001735 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1736 {
1737 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1738 width % formatInfo.compressedBlockWidth != 0) ||
1739 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1740 height % formatInfo.compressedBlockHeight != 0))
1741 {
1742 return false;
1743 }
1744 }
1745
Geoff Langd4f180b2013-09-24 13:57:44 -04001746 return true;
1747}
1748
Geoff Langff5b2d52016-09-07 11:32:23 -04001749bool ValidImageDataSize(ValidationContext *context,
1750 GLenum textureTarget,
1751 GLsizei width,
1752 GLsizei height,
1753 GLsizei depth,
1754 GLenum internalFormat,
1755 GLenum type,
1756 const GLvoid *pixels,
1757 GLsizei imageSize)
1758{
1759 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1760 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1761 {
1762 // Checks are not required
1763 return true;
1764 }
1765
1766 // ...the data would be unpacked from the buffer object such that the memory reads required
1767 // would exceed the data store size.
1768 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1769 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1770 const gl::Extents size(width, height, depth);
1771 const auto &unpack = context->getGLState().getUnpackState();
1772
1773 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1774 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1775 if (endByteOrErr.isError())
1776 {
1777 context->handleError(endByteOrErr.getError());
1778 return false;
1779 }
1780
1781 GLuint endByte = endByteOrErr.getResult();
1782
1783 if (pixelUnpackBuffer)
1784 {
1785 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1786 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1787 checkedEndByte += checkedOffset;
1788
1789 if (!checkedEndByte.IsValid() ||
1790 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1791 {
1792 // Overflow past the end of the buffer
1793 context->handleError(Error(GL_INVALID_OPERATION));
1794 return false;
1795 }
1796 }
1797 else
1798 {
1799 ASSERT(imageSize >= 0);
1800 if (pixels == nullptr && imageSize != 0)
1801 {
1802 context->handleError(
1803 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001804 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001805 }
1806
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001807 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001808 {
1809 context->handleError(
1810 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1811 return false;
1812 }
1813 }
1814
1815 return true;
1816}
1817
Geoff Lang37dde692014-01-31 16:34:54 -05001818bool ValidQueryType(const Context *context, GLenum queryType)
1819{
He Yunchaoced53ae2016-11-29 15:00:51 +08001820 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1821 "GL extension enums not equal.");
1822 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1823 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001824
1825 switch (queryType)
1826 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001827 case GL_ANY_SAMPLES_PASSED:
1828 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1829 return true;
1830 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1831 return (context->getClientMajorVersion() >= 3);
1832 case GL_TIME_ELAPSED_EXT:
1833 return context->getExtensions().disjointTimerQuery;
1834 case GL_COMMANDS_COMPLETED_CHROMIUM:
1835 return context->getExtensions().syncQuery;
1836 default:
1837 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001838 }
1839}
1840
Jamie Madillef300b12016-10-07 15:12:09 -04001841Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001842{
He Yunchaoced53ae2016-11-29 15:00:51 +08001843 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1844 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1845 // or program object and INVALID_OPERATION if the provided name identifies an object
1846 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001847
Dian Xiang769769a2015-09-09 15:20:08 -07001848 Program *validProgram = context->getProgram(id);
1849
1850 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001851 {
Dian Xiang769769a2015-09-09 15:20:08 -07001852 if (context->getShader(id))
1853 {
Jamie Madill437fa652016-05-03 15:13:24 -04001854 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001855 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1856 }
1857 else
1858 {
Jamie Madill437fa652016-05-03 15:13:24 -04001859 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001860 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001861 }
Dian Xiang769769a2015-09-09 15:20:08 -07001862
1863 return validProgram;
1864}
1865
Jamie Madillef300b12016-10-07 15:12:09 -04001866Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001867{
1868 // See ValidProgram for spec details.
1869
1870 Shader *validShader = context->getShader(id);
1871
1872 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001873 {
Dian Xiang769769a2015-09-09 15:20:08 -07001874 if (context->getProgram(id))
1875 {
Jamie Madill437fa652016-05-03 15:13:24 -04001876 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001877 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1878 }
1879 else
1880 {
Jamie Madill437fa652016-05-03 15:13:24 -04001881 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001882 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001883 }
Dian Xiang769769a2015-09-09 15:20:08 -07001884
1885 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001886}
1887
Geoff Langb1196682014-07-23 13:47:29 -04001888bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001889{
1890 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1891 {
1892 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1893
Geoff Langaae65a42014-05-26 12:43:44 -04001894 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001895 {
Jamie Madill437fa652016-05-03 15:13:24 -04001896 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001897 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001898 }
1899 }
1900 else
1901 {
1902 switch (attachment)
1903 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001904 case GL_DEPTH_ATTACHMENT:
1905 case GL_STENCIL_ATTACHMENT:
1906 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001907
He Yunchaoced53ae2016-11-29 15:00:51 +08001908 case GL_DEPTH_STENCIL_ATTACHMENT:
1909 if (!context->getExtensions().webglCompatibility &&
1910 context->getClientMajorVersion() < 3)
1911 {
1912 context->handleError(Error(GL_INVALID_ENUM));
1913 return false;
1914 }
1915 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001916
He Yunchaoced53ae2016-11-29 15:00:51 +08001917 default:
1918 context->handleError(Error(GL_INVALID_ENUM));
1919 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001920 }
1921 }
1922
1923 return true;
1924}
1925
He Yunchaoced53ae2016-11-29 15:00:51 +08001926bool ValidateRenderbufferStorageParametersBase(gl::Context *context,
1927 GLenum target,
1928 GLsizei samples,
1929 GLenum internalformat,
1930 GLsizei width,
1931 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001932{
1933 switch (target)
1934 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001935 case GL_RENDERBUFFER:
1936 break;
1937 default:
1938 context->handleError(Error(GL_INVALID_ENUM));
1939 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001940 }
1941
1942 if (width < 0 || height < 0 || samples < 0)
1943 {
Jamie Madill437fa652016-05-03 15:13:24 -04001944 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001945 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001946 }
1947
Geoff Langd87878e2014-09-19 15:42:59 -04001948 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1949 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001950 {
Jamie Madill437fa652016-05-03 15:13:24 -04001951 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001952 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001953 }
1954
1955 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1956 // 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 -08001957 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001958 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001959 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001960 {
Jamie Madill437fa652016-05-03 15:13:24 -04001961 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001962 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001963 }
1964
Geoff Langaae65a42014-05-26 12:43:44 -04001965 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001966 {
Jamie Madill437fa652016-05-03 15:13:24 -04001967 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001968 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001969 }
1970
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001971 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001972 if (handle == 0)
1973 {
Jamie Madill437fa652016-05-03 15:13:24 -04001974 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001975 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001976 }
1977
1978 return true;
1979}
1980
He Yunchaoced53ae2016-11-29 15:00:51 +08001981bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context,
1982 GLenum target,
1983 GLsizei samples,
1984 GLenum internalformat,
1985 GLsizei width,
1986 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -08001987{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001988 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001989
1990 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001991 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001992 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001993 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001994 {
Jamie Madill437fa652016-05-03 15:13:24 -04001995 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001996 return false;
1997 }
1998
1999 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
2000 // the specified storage. This is different than ES 3.0 in which a sample number higher
2001 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08002002 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03002003 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08002004 {
Geoff Langa4903b72015-03-02 16:02:48 -08002005 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2006 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2007 {
Jamie Madill437fa652016-05-03 15:13:24 -04002008 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08002009 return false;
2010 }
Corentin Walleze0902642014-11-04 12:32:15 -08002011 }
2012
He Yunchaoced53ae2016-11-29 15:00:51 +08002013 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
2014 width, height);
Corentin Walleze0902642014-11-04 12:32:15 -08002015}
2016
He Yunchaoced53ae2016-11-29 15:00:51 +08002017bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
2018 GLenum target,
2019 GLenum attachment,
2020 GLenum renderbuffertarget,
2021 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002022{
Shannon Woods1da3cf62014-06-27 15:32:23 -04002023 if (!ValidFramebufferTarget(target))
2024 {
Jamie Madill437fa652016-05-03 15:13:24 -04002025 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002026 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04002027 }
2028
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002029 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002030
Jamie Madill84115c92015-04-23 15:00:07 -04002031 ASSERT(framebuffer);
2032 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002033 {
Jamie Madill437fa652016-05-03 15:13:24 -04002034 context->handleError(
2035 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002036 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002037 }
2038
Jamie Madillb4472272014-07-03 10:38:55 -04002039 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002040 {
Jamie Madillb4472272014-07-03 10:38:55 -04002041 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002042 }
2043
Jamie Madillab9d82c2014-01-21 16:38:14 -05002044 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2045 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2046 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2047 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2048 if (renderbuffer != 0)
2049 {
2050 if (!context->getRenderbuffer(renderbuffer))
2051 {
Jamie Madill437fa652016-05-03 15:13:24 -04002052 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002053 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05002054 }
2055 }
2056
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002057 return true;
2058}
2059
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002060bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002061 GLint srcX0,
2062 GLint srcY0,
2063 GLint srcX1,
2064 GLint srcY1,
2065 GLint dstX0,
2066 GLint dstY0,
2067 GLint dstX1,
2068 GLint dstY1,
2069 GLbitfield mask,
2070 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002071{
2072 switch (filter)
2073 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002074 case GL_NEAREST:
2075 break;
2076 case GL_LINEAR:
2077 break;
2078 default:
2079 context->handleError(Error(GL_INVALID_ENUM));
2080 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002081 }
2082
2083 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
2084 {
Jamie Madill437fa652016-05-03 15:13:24 -04002085 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002086 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002087 }
2088
2089 if (mask == 0)
2090 {
2091 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
2092 // buffers are copied.
2093 return false;
2094 }
2095
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002096 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
2097 // color buffer, leaving only nearest being unfiltered from above
2098 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
2099 {
Jamie Madill437fa652016-05-03 15:13:24 -04002100 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002101 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002102 }
2103
Jamie Madill51f40ec2016-06-15 14:06:00 -04002104 const auto &glState = context->getGLState();
2105 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2106 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05002107
2108 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002109 {
Jamie Madill437fa652016-05-03 15:13:24 -04002110 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002111 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002112 }
2113
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002114 if (readFramebuffer->id() == drawFramebuffer->id())
2115 {
2116 context->handleError(Error(GL_INVALID_OPERATION));
2117 return false;
2118 }
2119
Jamie Madill51f40ec2016-06-15 14:06:00 -04002120 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002121 {
Jamie Madill437fa652016-05-03 15:13:24 -04002122 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002123 return false;
2124 }
2125
Jamie Madill51f40ec2016-06-15 14:06:00 -04002126 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002127 {
Jamie Madill437fa652016-05-03 15:13:24 -04002128 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002129 return false;
2130 }
2131
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002132 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002133 {
Jamie Madill437fa652016-05-03 15:13:24 -04002134 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002135 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002136 }
2137
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002138 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2139
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002140 if (mask & GL_COLOR_BUFFER_BIT)
2141 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002142 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002143 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002144
He Yunchao66a41a22016-12-15 16:45:05 +08002145 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002146 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002147 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002148
Geoff Langa15472a2015-08-11 11:48:03 -04002149 for (size_t drawbufferIdx = 0;
2150 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002151 {
Geoff Langa15472a2015-08-11 11:48:03 -04002152 const FramebufferAttachment *attachment =
2153 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2154 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002155 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002156 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002157
Geoff Langb2f3d052013-08-13 12:49:27 -04002158 // The GL ES 3.0.2 spec (pg 193) states that:
2159 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002160 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2161 // as well
2162 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2163 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002164 // Changes with EXT_color_buffer_float:
2165 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002166 GLenum readComponentType = readFormat.info->componentType;
2167 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002168 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002169 readComponentType == GL_SIGNED_NORMALIZED);
2170 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2171 drawComponentType == GL_SIGNED_NORMALIZED);
2172
2173 if (extensions.colorBufferFloat)
2174 {
2175 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2176 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2177
2178 if (readFixedOrFloat != drawFixedOrFloat)
2179 {
Jamie Madill437fa652016-05-03 15:13:24 -04002180 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002181 "If the read buffer contains fixed-point or "
2182 "floating-point values, the draw buffer "
2183 "must as well."));
2184 return false;
2185 }
2186 }
2187 else if (readFixedPoint != drawFixedPoint)
2188 {
Jamie Madill437fa652016-05-03 15:13:24 -04002189 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002190 "If the read buffer contains fixed-point "
2191 "values, the draw buffer must as well."));
2192 return false;
2193 }
2194
2195 if (readComponentType == GL_UNSIGNED_INT &&
2196 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002197 {
Jamie Madill437fa652016-05-03 15:13:24 -04002198 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002199 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002200 }
2201
Jamie Madill6163c752015-12-07 16:32:59 -05002202 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002203 {
Jamie Madill437fa652016-05-03 15:13:24 -04002204 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002205 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002206 }
2207
Jamie Madilla3944d42016-07-22 22:13:26 -04002208 if (readColorBuffer->getSamples() > 0 &&
2209 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002210 {
Jamie Madill437fa652016-05-03 15:13:24 -04002211 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002212 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002213 }
2214 }
2215 }
2216
Jamie Madilla3944d42016-07-22 22:13:26 -04002217 if ((readFormat.info->componentType == GL_INT ||
2218 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2219 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002220 {
Jamie Madill437fa652016-05-03 15:13:24 -04002221 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002222 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002223 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002224 }
He Yunchao66a41a22016-12-15 16:45:05 +08002225 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2226 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2227 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2228 // situation is an application error that would lead to a crash in ANGLE.
2229 else if (drawFramebuffer->hasEnabledDrawBuffer())
2230 {
2231 context->handleError(Error(
2232 GL_INVALID_OPERATION,
2233 "Attempt to read from a missing color attachment of a complete framebuffer."));
2234 return false;
2235 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002236 }
2237
He Yunchaoced53ae2016-11-29 15:00:51 +08002238 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002239 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2240 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002241 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002242 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002243 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002244 const gl::FramebufferAttachment *readBuffer =
2245 readFramebuffer->getAttachment(attachments[i]);
2246 const gl::FramebufferAttachment *drawBuffer =
2247 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002248
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002249 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002250 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002251 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002252 {
Jamie Madill437fa652016-05-03 15:13:24 -04002253 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002254 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002255 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002256
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002257 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002258 {
Jamie Madill437fa652016-05-03 15:13:24 -04002259 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002260 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002261 }
2262 }
He Yunchao66a41a22016-12-15 16:45:05 +08002263 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2264 else if (drawBuffer)
2265 {
2266 context->handleError(Error(GL_INVALID_OPERATION,
2267 "Attempt to read from a missing depth/stencil "
2268 "attachment of a complete framebuffer."));
2269 return false;
2270 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002271 }
2272 }
2273
2274 return true;
2275}
2276
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002277bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002278 GLint x,
2279 GLint y,
2280 GLsizei width,
2281 GLsizei height,
2282 GLenum format,
2283 GLenum type,
2284 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002285{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002286 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2287}
2288
2289bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2290 GLint x,
2291 GLint y,
2292 GLsizei width,
2293 GLsizei height,
2294 GLenum format,
2295 GLenum type,
2296 GLsizei bufSize,
2297 GLsizei *length,
2298 GLvoid *pixels)
2299{
2300 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002301 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002302 return false;
2303 }
2304
Geoff Lang62fce5b2016-09-30 10:46:35 -04002305 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2306 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002307 {
Geoff Langb1196682014-07-23 13:47:29 -04002308 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002309 }
2310
Geoff Lang62fce5b2016-09-30 10:46:35 -04002311 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002312 {
Geoff Langb1196682014-07-23 13:47:29 -04002313 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002314 }
2315
Jamie Madillc29968b2016-01-20 11:17:23 -05002316 return true;
2317}
2318
2319bool ValidateReadnPixelsEXT(Context *context,
2320 GLint x,
2321 GLint y,
2322 GLsizei width,
2323 GLsizei height,
2324 GLenum format,
2325 GLenum type,
2326 GLsizei bufSize,
2327 GLvoid *pixels)
2328{
2329 if (bufSize < 0)
2330 {
Jamie Madill437fa652016-05-03 15:13:24 -04002331 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002332 return false;
2333 }
2334
Geoff Lang62fce5b2016-09-30 10:46:35 -04002335 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2336 pixels);
2337}
Jamie Madill26e91952014-03-05 15:01:27 -05002338
Geoff Lang62fce5b2016-09-30 10:46:35 -04002339bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2340 GLint x,
2341 GLint y,
2342 GLsizei width,
2343 GLsizei height,
2344 GLenum format,
2345 GLenum type,
2346 GLsizei bufSize,
2347 GLsizei *length,
2348 GLvoid *data)
2349{
2350 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002351 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002352 return false;
2353 }
2354
Geoff Lang62fce5b2016-09-30 10:46:35 -04002355 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002356 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002357 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002358 }
2359
Geoff Lang62fce5b2016-09-30 10:46:35 -04002360 if (!ValidateRobustBufferSize(context, bufSize, *length))
2361 {
2362 return false;
2363 }
2364
2365 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002366}
2367
Olli Etuaho41997e72016-03-10 13:38:39 +02002368bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002369{
2370 if (!context->getExtensions().occlusionQueryBoolean &&
2371 !context->getExtensions().disjointTimerQuery)
2372 {
Jamie Madill437fa652016-05-03 15:13:24 -04002373 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002374 return false;
2375 }
2376
Olli Etuaho41997e72016-03-10 13:38:39 +02002377 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002378}
2379
Olli Etuaho41997e72016-03-10 13:38:39 +02002380bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002381{
2382 if (!context->getExtensions().occlusionQueryBoolean &&
2383 !context->getExtensions().disjointTimerQuery)
2384 {
Jamie Madill437fa652016-05-03 15:13:24 -04002385 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002386 return false;
2387 }
2388
Olli Etuaho41997e72016-03-10 13:38:39 +02002389 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002390}
2391
2392bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002393{
2394 if (!ValidQueryType(context, target))
2395 {
Jamie Madill437fa652016-05-03 15:13:24 -04002396 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002397 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002398 }
2399
2400 if (id == 0)
2401 {
Jamie Madill437fa652016-05-03 15:13:24 -04002402 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002403 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002404 }
2405
2406 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2407 // of zero, if the active query object name for <target> is non-zero (for the
2408 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2409 // the active query for either target is non-zero), if <id> is the name of an
2410 // existing query object whose type does not match <target>, or if <id> is the
2411 // active query object name for any query type, the error INVALID_OPERATION is
2412 // generated.
2413
2414 // Ensure no other queries are active
2415 // NOTE: If other queries than occlusion are supported, we will need to check
2416 // separately that:
2417 // a) The query ID passed is not the current active query for any target/type
2418 // b) There are no active queries for the requested target (and in the case
2419 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2420 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002421
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002422 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002423 {
Jamie Madill437fa652016-05-03 15:13:24 -04002424 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002425 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002426 }
2427
2428 Query *queryObject = context->getQuery(id, true, target);
2429
2430 // check that name was obtained with glGenQueries
2431 if (!queryObject)
2432 {
Jamie Madill437fa652016-05-03 15:13:24 -04002433 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002434 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002435 }
2436
2437 // check for type mismatch
2438 if (queryObject->getType() != target)
2439 {
Jamie Madill437fa652016-05-03 15:13:24 -04002440 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002441 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002442 }
2443
2444 return true;
2445}
2446
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002447bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2448{
2449 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002450 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002451 {
Jamie Madill437fa652016-05-03 15:13:24 -04002452 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002453 return false;
2454 }
2455
2456 return ValidateBeginQueryBase(context, target, id);
2457}
2458
2459bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002460{
2461 if (!ValidQueryType(context, target))
2462 {
Jamie Madill437fa652016-05-03 15:13:24 -04002463 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002464 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002465 }
2466
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002467 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002468
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002469 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002470 {
Jamie Madill437fa652016-05-03 15:13:24 -04002471 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002472 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002473 }
2474
Jamie Madill45c785d2014-05-13 14:09:34 -04002475 return true;
2476}
2477
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002478bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2479{
2480 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002481 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002482 {
Jamie Madill437fa652016-05-03 15:13:24 -04002483 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002484 return false;
2485 }
2486
2487 return ValidateEndQueryBase(context, target);
2488}
2489
2490bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2491{
2492 if (!context->getExtensions().disjointTimerQuery)
2493 {
Jamie Madill437fa652016-05-03 15:13:24 -04002494 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002495 return false;
2496 }
2497
2498 if (target != GL_TIMESTAMP_EXT)
2499 {
Jamie Madill437fa652016-05-03 15:13:24 -04002500 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002501 return false;
2502 }
2503
2504 Query *queryObject = context->getQuery(id, true, target);
2505 if (queryObject == nullptr)
2506 {
Jamie Madill437fa652016-05-03 15:13:24 -04002507 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002508 return false;
2509 }
2510
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002511 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002512 {
Jamie Madill437fa652016-05-03 15:13:24 -04002513 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002514 return false;
2515 }
2516
2517 return true;
2518}
2519
Geoff Lang2186c382016-10-14 10:54:54 -04002520bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002521{
Geoff Lang2186c382016-10-14 10:54:54 -04002522 if (numParams)
2523 {
2524 *numParams = 0;
2525 }
2526
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002527 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2528 {
Jamie Madill437fa652016-05-03 15:13:24 -04002529 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002530 return false;
2531 }
2532
2533 switch (pname)
2534 {
2535 case GL_CURRENT_QUERY_EXT:
2536 if (target == GL_TIMESTAMP_EXT)
2537 {
Jamie Madill437fa652016-05-03 15:13:24 -04002538 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002539 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2540 return false;
2541 }
2542 break;
2543 case GL_QUERY_COUNTER_BITS_EXT:
2544 if (!context->getExtensions().disjointTimerQuery ||
2545 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2546 {
Jamie Madill437fa652016-05-03 15:13:24 -04002547 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002548 return false;
2549 }
2550 break;
2551 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002552 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002553 return false;
2554 }
2555
Geoff Lang2186c382016-10-14 10:54:54 -04002556 if (numParams)
2557 {
2558 // All queries return only one value
2559 *numParams = 1;
2560 }
2561
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002562 return true;
2563}
2564
2565bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2566{
2567 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002568 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002569 {
Jamie Madill437fa652016-05-03 15:13:24 -04002570 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002571 return false;
2572 }
2573
Geoff Lang2186c382016-10-14 10:54:54 -04002574 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002575}
2576
Geoff Lang2186c382016-10-14 10:54:54 -04002577bool ValidateGetQueryivRobustANGLE(Context *context,
2578 GLenum target,
2579 GLenum pname,
2580 GLsizei bufSize,
2581 GLsizei *length,
2582 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002583{
Geoff Lang2186c382016-10-14 10:54:54 -04002584 if (!ValidateRobustEntryPoint(context, bufSize))
2585 {
2586 return false;
2587 }
2588
2589 if (!ValidateGetQueryivBase(context, target, pname, length))
2590 {
2591 return false;
2592 }
2593
2594 if (!ValidateRobustBufferSize(context, bufSize, *length))
2595 {
2596 return false;
2597 }
2598
2599 return true;
2600}
2601
2602bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2603{
2604 if (numParams)
2605 {
2606 *numParams = 0;
2607 }
2608
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002609 Query *queryObject = context->getQuery(id, false, GL_NONE);
2610
2611 if (!queryObject)
2612 {
Jamie Madill437fa652016-05-03 15:13:24 -04002613 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002614 return false;
2615 }
2616
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002617 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002618 {
Jamie Madill437fa652016-05-03 15:13:24 -04002619 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002620 return false;
2621 }
2622
2623 switch (pname)
2624 {
2625 case GL_QUERY_RESULT_EXT:
2626 case GL_QUERY_RESULT_AVAILABLE_EXT:
2627 break;
2628
2629 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002630 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002631 return false;
2632 }
2633
Geoff Lang2186c382016-10-14 10:54:54 -04002634 if (numParams)
2635 {
2636 *numParams = 1;
2637 }
2638
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002639 return true;
2640}
2641
2642bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2643{
2644 if (!context->getExtensions().disjointTimerQuery)
2645 {
Jamie Madill437fa652016-05-03 15:13:24 -04002646 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002647 return false;
2648 }
Geoff Lang2186c382016-10-14 10:54:54 -04002649 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2650}
2651
2652bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2653 GLuint id,
2654 GLenum pname,
2655 GLsizei bufSize,
2656 GLsizei *length,
2657 GLint *params)
2658{
2659 if (!context->getExtensions().disjointTimerQuery)
2660 {
2661 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2662 return false;
2663 }
2664
2665 if (!ValidateRobustEntryPoint(context, bufSize))
2666 {
2667 return false;
2668 }
2669
2670 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2671 {
2672 return false;
2673 }
2674
2675 if (!ValidateRobustBufferSize(context, bufSize, *length))
2676 {
2677 return false;
2678 }
2679
2680 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002681}
2682
2683bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2684{
2685 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002686 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002687 {
Jamie Madill437fa652016-05-03 15:13:24 -04002688 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002689 return false;
2690 }
Geoff Lang2186c382016-10-14 10:54:54 -04002691 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2692}
2693
2694bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2695 GLuint id,
2696 GLenum pname,
2697 GLsizei bufSize,
2698 GLsizei *length,
2699 GLuint *params)
2700{
2701 if (!context->getExtensions().disjointTimerQuery &&
2702 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2703 {
2704 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2705 return false;
2706 }
2707
2708 if (!ValidateRobustEntryPoint(context, bufSize))
2709 {
2710 return false;
2711 }
2712
2713 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2714 {
2715 return false;
2716 }
2717
2718 if (!ValidateRobustBufferSize(context, bufSize, *length))
2719 {
2720 return false;
2721 }
2722
2723 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002724}
2725
2726bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2727{
2728 if (!context->getExtensions().disjointTimerQuery)
2729 {
Jamie Madill437fa652016-05-03 15:13:24 -04002730 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002731 return false;
2732 }
Geoff Lang2186c382016-10-14 10:54:54 -04002733 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2734}
2735
2736bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2737 GLuint id,
2738 GLenum pname,
2739 GLsizei bufSize,
2740 GLsizei *length,
2741 GLint64 *params)
2742{
2743 if (!context->getExtensions().disjointTimerQuery)
2744 {
2745 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2746 return false;
2747 }
2748
2749 if (!ValidateRobustEntryPoint(context, bufSize))
2750 {
2751 return false;
2752 }
2753
2754 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2755 {
2756 return false;
2757 }
2758
2759 if (!ValidateRobustBufferSize(context, bufSize, *length))
2760 {
2761 return false;
2762 }
2763
2764 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002765}
2766
2767bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2768{
2769 if (!context->getExtensions().disjointTimerQuery)
2770 {
Jamie Madill437fa652016-05-03 15:13:24 -04002771 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002772 return false;
2773 }
Geoff Lang2186c382016-10-14 10:54:54 -04002774 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2775}
2776
2777bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2778 GLuint id,
2779 GLenum pname,
2780 GLsizei bufSize,
2781 GLsizei *length,
2782 GLuint64 *params)
2783{
2784 if (!context->getExtensions().disjointTimerQuery)
2785 {
2786 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2787 return false;
2788 }
2789
2790 if (!ValidateRobustEntryPoint(context, bufSize))
2791 {
2792 return false;
2793 }
2794
2795 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2796 {
2797 return false;
2798 }
2799
2800 if (!ValidateRobustBufferSize(context, bufSize, *length))
2801 {
2802 return false;
2803 }
2804
2805 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002806}
2807
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002808bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002809 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002810 GLuint program,
2811 GLint location,
2812 GLsizei count)
2813{
2814 // Check for ES31 program uniform entry points
2815 if (context->getClientVersion() < Version(3, 1))
2816 {
2817 context->handleError(Error(GL_INVALID_OPERATION));
2818 return false;
2819 }
2820
2821 const LinkedUniform *uniform = nullptr;
2822 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002823 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2824 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002825}
2826
Frank Henigmana98a6472017-02-02 21:38:32 -05002827bool ValidateProgramUniform1iv(gl::Context *context,
2828 GLuint program,
2829 GLint location,
2830 GLsizei count,
2831 const GLint *value)
2832{
2833 // Check for ES31 program uniform entry points
2834 if (context->getClientVersion() < Version(3, 1))
2835 {
2836 context->handleError(Error(GL_INVALID_OPERATION));
2837 return false;
2838 }
2839
2840 const LinkedUniform *uniform = nullptr;
2841 gl::Program *programObject = GetValidProgram(context, program);
2842 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2843 ValidateUniform1ivValue(context, uniform->type, count, value);
2844}
2845
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002846bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002847 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002848 GLuint program,
2849 GLint location,
2850 GLsizei count,
2851 GLboolean transpose)
2852{
2853 // Check for ES31 program uniform entry points
2854 if (context->getClientVersion() < Version(3, 1))
2855 {
2856 context->handleError(Error(GL_INVALID_OPERATION));
2857 return false;
2858 }
2859
2860 const LinkedUniform *uniform = nullptr;
2861 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002862 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2863 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002864}
2865
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002866bool ValidateUniform(gl::Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002867{
2868 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002869 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002870 {
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 Madillaa981bd2014-05-20 10:55:55 -04002873 }
2874
Jamie Madill62d31cb2015-09-11 13:25:51 -04002875 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002876 gl::Program *programObject = context->getGLState().getProgram();
2877 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2878 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002879}
2880
Frank Henigmana98a6472017-02-02 21:38:32 -05002881bool ValidateUniform1iv(gl::Context *context, GLint location, GLsizei count, const GLint *value)
2882{
2883 const LinkedUniform *uniform = nullptr;
2884 gl::Program *programObject = context->getGLState().getProgram();
2885 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2886 ValidateUniform1ivValue(context, uniform->type, count, value);
2887}
2888
He Yunchaoced53ae2016-11-29 15:00:51 +08002889bool ValidateUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002890 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002891 GLint location,
2892 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002893 GLboolean transpose)
2894{
2895 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002896 int rows = VariableRowCount(valueType);
2897 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002898 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002899 {
Jamie Madill437fa652016-05-03 15:13:24 -04002900 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002901 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002902 }
2903
Martin Radev1be913c2016-07-11 17:59:16 +03002904 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002905 {
Jamie Madill437fa652016-05-03 15:13:24 -04002906 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002907 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002908 }
2909
Jamie Madill62d31cb2015-09-11 13:25:51 -04002910 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002911 gl::Program *programObject = context->getGLState().getProgram();
2912 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2913 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002914}
2915
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002916bool ValidateStateQuery(ValidationContext *context,
2917 GLenum pname,
2918 GLenum *nativeType,
2919 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002920{
2921 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2922 {
Jamie Madill437fa652016-05-03 15:13:24 -04002923 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002924 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002925 }
2926
Jamie Madill0af26e12015-03-05 19:54:33 -05002927 const Caps &caps = context->getCaps();
2928
Jamie Madill893ab082014-05-16 16:56:10 -04002929 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2930 {
2931 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2932
Jamie Madill0af26e12015-03-05 19:54:33 -05002933 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002934 {
Jamie Madill437fa652016-05-03 15:13:24 -04002935 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002936 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002937 }
2938 }
2939
2940 switch (pname)
2941 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002942 case GL_TEXTURE_BINDING_2D:
2943 case GL_TEXTURE_BINDING_CUBE_MAP:
2944 case GL_TEXTURE_BINDING_3D:
2945 case GL_TEXTURE_BINDING_2D_ARRAY:
2946 break;
2947 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2948 if (!context->getExtensions().eglStreamConsumerExternal &&
2949 !context->getExtensions().eglImageExternal)
2950 {
2951 context->handleError(Error(GL_INVALID_ENUM,
2952 "Neither NV_EGL_stream_consumer_external nor "
2953 "GL_OES_EGL_image_external extensions enabled"));
2954 return false;
2955 }
2956 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002957
He Yunchaoced53ae2016-11-29 15:00:51 +08002958 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2959 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002960 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002961 if (context->getGLState().getReadFramebuffer()->checkStatus(
2962 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002963 {
Jamie Madill437fa652016-05-03 15:13:24 -04002964 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002965 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002966 }
2967
Jamie Madill51f40ec2016-06-15 14:06:00 -04002968 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2969 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002970
2971 if (framebuffer->getReadBufferState() == GL_NONE)
2972 {
2973 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2974 return false;
2975 }
2976
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002977 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002978 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002979 {
Jamie Madill437fa652016-05-03 15:13:24 -04002980 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002981 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002982 }
2983 }
2984 break;
2985
He Yunchaoced53ae2016-11-29 15:00:51 +08002986 default:
2987 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002988 }
2989
2990 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002991 if (*numParams == 0)
2992 {
2993 return false;
2994 }
2995
2996 return true;
2997}
2998
2999bool ValidateRobustStateQuery(ValidationContext *context,
3000 GLenum pname,
3001 GLsizei bufSize,
3002 GLenum *nativeType,
3003 unsigned int *numParams)
3004{
3005 if (!ValidateRobustEntryPoint(context, bufSize))
3006 {
3007 return false;
3008 }
3009
3010 if (!ValidateStateQuery(context, pname, nativeType, numParams))
3011 {
3012 return false;
3013 }
3014
3015 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04003016 {
3017 return false;
3018 }
3019
3020 return true;
3021}
3022
Jamie Madillc29968b2016-01-20 11:17:23 -05003023bool ValidateCopyTexImageParametersBase(ValidationContext *context,
3024 GLenum target,
3025 GLint level,
3026 GLenum internalformat,
3027 bool isSubImage,
3028 GLint xoffset,
3029 GLint yoffset,
3030 GLint zoffset,
3031 GLint x,
3032 GLint y,
3033 GLsizei width,
3034 GLsizei height,
3035 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04003036 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04003037{
Jamie Madill560a8d82014-05-21 13:06:20 -04003038 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
3039 {
Jamie Madill437fa652016-05-03 15:13:24 -04003040 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003041 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003042 }
3043
He Yunchaoced53ae2016-11-29 15:00:51 +08003044 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3045 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04003046 {
Jamie Madill437fa652016-05-03 15:13:24 -04003047 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003048 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003049 }
3050
3051 if (border != 0)
3052 {
Jamie Madill437fa652016-05-03 15:13:24 -04003053 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003054 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003055 }
3056
3057 if (!ValidMipLevel(context, target, level))
3058 {
Jamie Madill437fa652016-05-03 15:13:24 -04003059 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003060 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003061 }
3062
Jamie Madill51f40ec2016-06-15 14:06:00 -04003063 const auto &state = context->getGLState();
3064 auto readFramebuffer = state.getReadFramebuffer();
3065 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003066 {
Jamie Madill437fa652016-05-03 15:13:24 -04003067 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003068 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003069 }
3070
Jamie Madill51f40ec2016-06-15 14:06:00 -04003071 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003072 {
Jamie Madill437fa652016-05-03 15:13:24 -04003073 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003074 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003075 }
3076
Martin Radev138064f2016-07-15 12:03:41 +03003077 if (readFramebuffer->getReadBufferState() == GL_NONE)
3078 {
3079 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3080 return false;
3081 }
3082
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003083 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3084 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003085 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003086 // situation is an application error that would lead to a crash in ANGLE.
3087 if (readFramebuffer->getReadColorbuffer() == nullptr)
3088 {
3089 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3090 return false;
3091 }
3092
Geoff Langaae65a42014-05-26 12:43:44 -04003093 const gl::Caps &caps = context->getCaps();
3094
Geoff Langaae65a42014-05-26 12:43:44 -04003095 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003096 switch (target)
3097 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003098 case GL_TEXTURE_2D:
3099 maxDimension = caps.max2DTextureSize;
3100 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003101
He Yunchaoced53ae2016-11-29 15:00:51 +08003102 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3103 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3104 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3105 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3106 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3107 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3108 maxDimension = caps.maxCubeMapTextureSize;
3109 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003110
He Yunchaoced53ae2016-11-29 15:00:51 +08003111 case GL_TEXTURE_2D_ARRAY:
3112 maxDimension = caps.max2DTextureSize;
3113 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003114
He Yunchaoced53ae2016-11-29 15:00:51 +08003115 case GL_TEXTURE_3D:
3116 maxDimension = caps.max3DTextureSize;
3117 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003118
He Yunchaoced53ae2016-11-29 15:00:51 +08003119 default:
3120 context->handleError(Error(GL_INVALID_ENUM));
3121 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003122 }
3123
Jamie Madillc29968b2016-01-20 11:17:23 -05003124 gl::Texture *texture =
3125 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003126 if (!texture)
3127 {
Jamie Madill437fa652016-05-03 15:13:24 -04003128 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003129 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003130 }
3131
Geoff Lang69cce582015-09-17 13:20:36 -04003132 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003133 {
Jamie Madill437fa652016-05-03 15:13:24 -04003134 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003135 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003136 }
3137
Geoff Lang5d601382014-07-22 15:14:06 -04003138 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3139
3140 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003141 {
Jamie Madill437fa652016-05-03 15:13:24 -04003142 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003143 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003144 }
3145
Geoff Langa9be0dc2014-12-17 12:34:40 -05003146 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003147 {
Jamie Madill437fa652016-05-03 15:13:24 -04003148 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003149 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003150 }
3151
3152 if (isSubImage)
3153 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003154 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3155 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3156 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003157 {
Jamie Madill437fa652016-05-03 15:13:24 -04003158 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003159 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003160 }
3161 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003162 else
3163 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003164 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003165 {
Jamie Madill437fa652016-05-03 15:13:24 -04003166 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003167 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003168 }
3169
Geoff Langeb66a6e2016-10-31 13:06:12 -04003170 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003171 {
Jamie Madill437fa652016-05-03 15:13:24 -04003172 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003173 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003174 }
3175
3176 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003177 if (static_cast<int>(width) > maxLevelDimension ||
3178 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003179 {
Jamie Madill437fa652016-05-03 15:13:24 -04003180 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003181 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003182 }
3183 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003184
Jamie Madill0c8abca2016-07-22 20:21:26 -04003185 if (textureFormatOut)
3186 {
3187 *textureFormatOut = texture->getFormat(target, level);
3188 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003189
3190 // Detect texture copying feedback loops for WebGL.
3191 if (context->getExtensions().webglCompatibility)
3192 {
3193 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level))
3194 {
3195 context->handleError(Error(GL_INVALID_OPERATION,
3196 "Texture copying feedback loop formed between Framebuffer "
3197 "and specified Texture level."));
3198 return false;
3199 }
3200 }
3201
Jamie Madill560a8d82014-05-21 13:06:20 -04003202 return true;
3203}
3204
Jiajia Qind9671222016-11-29 16:30:31 +08003205bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003206{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003207 switch (mode)
3208 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003209 case GL_POINTS:
3210 case GL_LINES:
3211 case GL_LINE_LOOP:
3212 case GL_LINE_STRIP:
3213 case GL_TRIANGLES:
3214 case GL_TRIANGLE_STRIP:
3215 case GL_TRIANGLE_FAN:
3216 break;
3217 default:
3218 context->handleError(Error(GL_INVALID_ENUM));
3219 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003220 }
3221
Jamie Madill250d33f2014-06-06 17:09:03 -04003222 if (count < 0)
3223 {
Jamie Madill437fa652016-05-03 15:13:24 -04003224 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003225 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003226 }
3227
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003228 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003229
Jamie Madill250d33f2014-06-06 17:09:03 -04003230 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003231 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003232 {
Jamie Madill437fa652016-05-03 15:13:24 -04003233 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003234 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003235 }
3236
Jamie Madillcbcde722017-01-06 14:50:00 -05003237 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3238 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003239 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003240 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3241 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003242 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003243 const FramebufferAttachment *dsAttachment =
3244 framebuffer->getStencilOrDepthStencilAttachment();
3245 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003246 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003247 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003248
3249 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3250 bool differentWritemasks =
3251 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3252 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3253 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3254 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3255
3256 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003257 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003258 if (!context->getExtensions().webglCompatibility)
3259 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003260 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3261 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003262 }
Jamie Madill437fa652016-05-03 15:13:24 -04003263 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003264 return false;
3265 }
Jamie Madillac528012014-06-20 13:21:23 -04003266 }
3267
Jamie Madill51f40ec2016-06-15 14:06:00 -04003268 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003269 {
Jamie Madill437fa652016-05-03 15:13:24 -04003270 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003271 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003272 }
3273
Geoff Lang7dd2e102014-11-10 15:19:26 -05003274 gl::Program *program = state.getProgram();
3275 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003276 {
Jamie Madill437fa652016-05-03 15:13:24 -04003277 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003278 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003279 }
3280
Geoff Lang7dd2e102014-11-10 15:19:26 -05003281 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003282 {
Jamie Madill437fa652016-05-03 15:13:24 -04003283 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003284 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003285 }
3286
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003287 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003288 for (unsigned int uniformBlockIndex = 0;
3289 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003290 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003291 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003292 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003293 const OffsetBindingPointer<Buffer> &uniformBuffer =
3294 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003295
Geoff Lang5d124a62015-09-15 13:03:27 -04003296 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003297 {
3298 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003299 context->handleError(
3300 Error(GL_INVALID_OPERATION,
3301 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003302 return false;
3303 }
3304
Geoff Lang5d124a62015-09-15 13:03:27 -04003305 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003306 if (uniformBufferSize == 0)
3307 {
3308 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003309 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003310 }
3311
Jamie Madill62d31cb2015-09-11 13:25:51 -04003312 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003313 {
3314 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003315 context->handleError(
3316 Error(GL_INVALID_OPERATION,
3317 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003318 return false;
3319 }
3320 }
3321
Jamie Madilla4595b82017-01-11 17:36:34 -05003322 // Detect rendering feedback loops for WebGL.
3323 if (context->getExtensions().webglCompatibility)
3324 {
3325 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3326 {
3327 context->handleError(
3328 Error(GL_INVALID_OPERATION,
3329 "Rendering feedback loop formed between Framebuffer and active Texture."));
3330 return false;
3331 }
3332 }
3333
Jamie Madill250d33f2014-06-06 17:09:03 -04003334 // No-op if zero count
3335 return (count > 0);
3336}
3337
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003338bool ValidateDrawArrays(ValidationContext *context,
3339 GLenum mode,
3340 GLint first,
3341 GLsizei count,
3342 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003343{
Jamie Madillfd716582014-06-06 17:09:04 -04003344 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003345 {
Jamie Madill437fa652016-05-03 15:13:24 -04003346 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003347 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003348 }
3349
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003350 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003351 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003352 if (curTransformFeedback && curTransformFeedback->isActive() &&
3353 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003354 {
3355 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003356 // that does not match the current transform feedback object's draw mode (if transform
3357 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003358 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003359 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003360 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003361 }
3362
Jiajia Qind9671222016-11-29 16:30:31 +08003363 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003364 {
3365 return false;
3366 }
3367
Corentin Wallez71168a02016-12-19 15:11:18 -08003368 // Check the computation of maxVertex doesn't overflow.
3369 // - first < 0 or count < 0 have been checked as an error condition
3370 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3371 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3372 ASSERT(count > 0 && first >= 0);
3373 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3374 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003375 {
3376 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3377 return false;
3378 }
3379
Corentin Wallez71168a02016-12-19 15:11:18 -08003380 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003381 {
3382 return false;
3383 }
3384
3385 return true;
3386}
3387
He Yunchaoced53ae2016-11-29 15:00:51 +08003388bool ValidateDrawArraysInstanced(Context *context,
3389 GLenum mode,
3390 GLint first,
3391 GLsizei count,
3392 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003393{
3394 if (primcount < 0)
3395 {
Jamie Madill437fa652016-05-03 15:13:24 -04003396 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003397 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003398 }
3399
Jamie Madill2b976812014-08-25 15:47:49 -04003400 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003401 {
3402 return false;
3403 }
3404
3405 // No-op if zero primitive count
3406 return (primcount > 0);
3407}
3408
Geoff Lang87a93302014-09-16 13:29:43 -04003409static bool ValidateDrawInstancedANGLE(Context *context)
3410{
3411 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003412 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003413
Geoff Lang7dd2e102014-11-10 15:19:26 -05003414 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003415
3416 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003417 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003418 {
3419 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003420 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003421 {
3422 return true;
3423 }
3424 }
3425
Jamie Madill437fa652016-05-03 15:13:24 -04003426 context->handleError(Error(GL_INVALID_OPERATION,
3427 "ANGLE_instanced_arrays requires that at least one active attribute"
3428 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003429 return false;
3430}
3431
He Yunchaoced53ae2016-11-29 15:00:51 +08003432bool ValidateDrawArraysInstancedANGLE(Context *context,
3433 GLenum mode,
3434 GLint first,
3435 GLsizei count,
3436 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003437{
3438 if (!ValidateDrawInstancedANGLE(context))
3439 {
3440 return false;
3441 }
3442
3443 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3444}
3445
Jiajia Qind9671222016-11-29 16:30:31 +08003446bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003447{
Jamie Madill250d33f2014-06-06 17:09:03 -04003448 switch (type)
3449 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003450 case GL_UNSIGNED_BYTE:
3451 case GL_UNSIGNED_SHORT:
3452 break;
3453 case GL_UNSIGNED_INT:
3454 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3455 {
3456 context->handleError(Error(GL_INVALID_ENUM));
3457 return false;
3458 }
3459 break;
3460 default:
3461 context->handleError(Error(GL_INVALID_ENUM));
3462 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003463 }
3464
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003465 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003466
3467 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003468 if (curTransformFeedback && curTransformFeedback->isActive() &&
3469 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003470 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003471 // It is an invalid operation to call DrawElements, DrawRangeElements or
3472 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003473 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003474 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003475 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003476 }
3477
Jiajia Qind9671222016-11-29 16:30:31 +08003478 return true;
3479}
3480
3481bool ValidateDrawElements(ValidationContext *context,
3482 GLenum mode,
3483 GLsizei count,
3484 GLenum type,
3485 const GLvoid *indices,
3486 GLsizei primcount,
3487 IndexRange *indexRangeOut)
3488{
3489 if (!ValidateDrawElementsBase(context, type))
3490 return false;
3491
3492 const State &state = context->getGLState();
3493
Jamie Madill250d33f2014-06-06 17:09:03 -04003494 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003495 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003496 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003497 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04003498 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003499 }
3500
He Yunchaoced53ae2016-11-29 15:00:51 +08003501 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003502 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003503
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003504 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3505
3506 if (context->getExtensions().webglCompatibility)
3507 {
3508 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3509 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3510 {
3511 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3512 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3513 // data type passed to the call, or an INVALID_OPERATION error is generated.
3514 context->handleError(Error(GL_INVALID_OPERATION,
3515 "indices must be a multiple of the element type size."));
3516 return false;
3517 }
3518 if (!elementArrayBuffer && count > 0)
3519 {
3520 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3521 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3522 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3523 context->handleError(Error(GL_INVALID_OPERATION,
3524 "There is no element array buffer bound and count > 0."));
3525 return false;
3526 }
3527 }
3528
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003529 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003530 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003531 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003532 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003533 GLint64 offset = reinterpret_cast<GLint64>(indices);
3534 GLint64 byteCount =
3535 static_cast<GLint64>(typeBytes) * static_cast<GLint64>(count) + offset;
3536
3537 // check for integer overflows
3538 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeBytes) ||
3539 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3540 {
3541 context->handleError(Error(GL_OUT_OF_MEMORY, "Integer overflow."));
3542 return false;
3543 }
3544
3545 // Check for reading past the end of the bound buffer object
3546 if (byteCount > elementArrayBuffer->getSize())
3547 {
3548 context->handleError(
3549 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
3550 return false;
3551 }
3552 }
3553 else if (!indices)
3554 {
3555 // This is an application error that would normally result in a crash,
3556 // but we catch it and return an error
3557 context->handleError(
3558 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003559 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003560 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003561 }
3562
Jiajia Qind9671222016-11-29 16:30:31 +08003563 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003564 {
3565 return false;
3566 }
3567
Jamie Madill2b976812014-08-25 15:47:49 -04003568 // Use max index to validate if our vertex buffers are large enough for the pull.
3569 // TODO: offer fast path, with disabled index validation.
3570 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3571 if (elementArrayBuffer)
3572 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003573 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003574 Error error =
3575 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3576 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003577 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003578 {
Jamie Madill437fa652016-05-03 15:13:24 -04003579 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003580 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003581 }
3582 }
3583 else
3584 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003585 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003586 }
3587
Jamie Madille79b1e12015-11-04 16:36:37 -05003588 // If we use an index greater than our maximum supported index range, return an error.
3589 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3590 // return an error if possible here.
3591 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3592 {
Jamie Madill437fa652016-05-03 15:13:24 -04003593 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003594 return false;
3595 }
3596
Corentin Wallez92db6942016-12-09 13:10:36 -05003597 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3598 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003599 {
3600 return false;
3601 }
3602
Geoff Lang3edfe032015-09-04 16:38:24 -04003603 // No op if there are no real indices in the index data (all are primitive restart).
3604 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003605}
3606
Geoff Langb1196682014-07-23 13:47:29 -04003607bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003608 GLenum mode,
3609 GLsizei count,
3610 GLenum type,
3611 const GLvoid *indices,
3612 GLsizei primcount,
3613 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003614{
3615 if (primcount < 0)
3616 {
Jamie Madill437fa652016-05-03 15:13:24 -04003617 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003618 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003619 }
3620
Jamie Madill2b976812014-08-25 15:47:49 -04003621 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003622 {
3623 return false;
3624 }
3625
3626 // No-op zero primitive count
3627 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003628}
3629
Geoff Lang3edfe032015-09-04 16:38:24 -04003630bool ValidateDrawElementsInstancedANGLE(Context *context,
3631 GLenum mode,
3632 GLsizei count,
3633 GLenum type,
3634 const GLvoid *indices,
3635 GLsizei primcount,
3636 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003637{
3638 if (!ValidateDrawInstancedANGLE(context))
3639 {
3640 return false;
3641 }
3642
He Yunchaoced53ae2016-11-29 15:00:51 +08003643 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3644 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003645}
3646
He Yunchaoced53ae2016-11-29 15:00:51 +08003647bool ValidateFramebufferTextureBase(Context *context,
3648 GLenum target,
3649 GLenum attachment,
3650 GLuint texture,
3651 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003652{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003653 if (!ValidFramebufferTarget(target))
3654 {
Jamie Madill437fa652016-05-03 15:13:24 -04003655 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003656 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003657 }
3658
3659 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003660 {
3661 return false;
3662 }
3663
Jamie Madill55ec3b12014-07-03 10:38:57 -04003664 if (texture != 0)
3665 {
3666 gl::Texture *tex = context->getTexture(texture);
3667
3668 if (tex == NULL)
3669 {
Jamie Madill437fa652016-05-03 15:13:24 -04003670 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003671 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003672 }
3673
3674 if (level < 0)
3675 {
Jamie Madill437fa652016-05-03 15:13:24 -04003676 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003677 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003678 }
3679 }
3680
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003681 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003682 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003683
Jamie Madill84115c92015-04-23 15:00:07 -04003684 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003685 {
Jamie Madill437fa652016-05-03 15:13:24 -04003686 context->handleError(
3687 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003688 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003689 }
3690
3691 return true;
3692}
3693
He Yunchaoced53ae2016-11-29 15:00:51 +08003694bool ValidateFramebufferTexture2D(Context *context,
3695 GLenum target,
3696 GLenum attachment,
3697 GLenum textarget,
3698 GLuint texture,
3699 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003700{
He Yunchaoced53ae2016-11-29 15:00:51 +08003701 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3702 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003703 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3704 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003705 {
Jamie Madill437fa652016-05-03 15:13:24 -04003706 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003707 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003708 }
3709
3710 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003711 {
3712 return false;
3713 }
3714
Jamie Madill55ec3b12014-07-03 10:38:57 -04003715 if (texture != 0)
3716 {
3717 gl::Texture *tex = context->getTexture(texture);
3718 ASSERT(tex);
3719
Jamie Madill2a6564e2014-07-11 09:53:19 -04003720 const gl::Caps &caps = context->getCaps();
3721
Jamie Madill55ec3b12014-07-03 10:38:57 -04003722 switch (textarget)
3723 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003724 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003725 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003726 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003727 {
Jamie Madill437fa652016-05-03 15:13:24 -04003728 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003729 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003730 }
3731 if (tex->getTarget() != GL_TEXTURE_2D)
3732 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003733 context->handleError(Error(GL_INVALID_OPERATION,
3734 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003735 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003736 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003737 }
3738 break;
3739
He Yunchaoced53ae2016-11-29 15:00:51 +08003740 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3741 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3742 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3743 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3744 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3745 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003746 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003747 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003748 {
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 Madill55ec3b12014-07-03 10:38:57 -04003751 }
3752 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3753 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003754 context->handleError(Error(GL_INVALID_OPERATION,
3755 "Textarget must match the texture target type."));
3756 return false;
3757 }
3758 }
3759 break;
3760
3761 case GL_TEXTURE_2D_MULTISAMPLE:
3762 {
3763 if (context->getClientVersion() < ES_3_1)
3764 {
3765 context->handleError(Error(GL_INVALID_OPERATION,
3766 "Texture target requires at least OpenGL ES 3.1."));
3767 return false;
3768 }
3769
3770 if (level != 0)
3771 {
3772 context->handleError(
3773 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
3774 return false;
3775 }
3776 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
3777 {
3778 context->handleError(Error(GL_INVALID_OPERATION,
3779 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003780 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003781 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003782 }
3783 break;
3784
He Yunchaoced53ae2016-11-29 15:00:51 +08003785 default:
3786 context->handleError(Error(GL_INVALID_ENUM));
3787 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003788 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003789
Jamie Madilla3944d42016-07-22 22:13:26 -04003790 const Format &format = tex->getFormat(textarget, level);
3791 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003792 {
Jamie Madill437fa652016-05-03 15:13:24 -04003793 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003794 return false;
3795 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003796 }
3797
Jamie Madill570f7c82014-07-03 10:38:54 -04003798 return true;
3799}
3800
Geoff Langb1196682014-07-23 13:47:29 -04003801bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003802{
3803 if (program == 0)
3804 {
Jamie Madill437fa652016-05-03 15:13:24 -04003805 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003806 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003807 }
3808
Dian Xiang769769a2015-09-09 15:20:08 -07003809 gl::Program *programObject = GetValidProgram(context, program);
3810 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003811 {
3812 return false;
3813 }
3814
Jamie Madill0063c512014-08-25 15:47:53 -04003815 if (!programObject || !programObject->isLinked())
3816 {
Jamie Madill437fa652016-05-03 15:13:24 -04003817 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003818 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003819 }
3820
Geoff Lang7dd2e102014-11-10 15:19:26 -05003821 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003822 {
Jamie Madill437fa652016-05-03 15:13:24 -04003823 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003824 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003825 }
3826
Jamie Madill0063c512014-08-25 15:47:53 -04003827 return true;
3828}
3829
He Yunchaoced53ae2016-11-29 15:00:51 +08003830bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003831{
3832 return ValidateGetUniformBase(context, program, location);
3833}
3834
He Yunchaoced53ae2016-11-29 15:00:51 +08003835bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003836{
Jamie Madill78f41802014-08-25 15:47:55 -04003837 return ValidateGetUniformBase(context, program, location);
3838}
3839
Geoff Langf41d0ee2016-10-07 13:04:23 -04003840static bool ValidateSizedGetUniform(Context *context,
3841 GLuint program,
3842 GLint location,
3843 GLsizei bufSize,
3844 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003845{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003846 if (length)
3847 {
3848 *length = 0;
3849 }
3850
Jamie Madill78f41802014-08-25 15:47:55 -04003851 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003852 {
Jamie Madill78f41802014-08-25 15:47:55 -04003853 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003854 }
3855
Geoff Langf41d0ee2016-10-07 13:04:23 -04003856 if (bufSize < 0)
3857 {
3858 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3859 return false;
3860 }
3861
Jamie Madilla502c742014-08-28 17:19:13 -04003862 gl::Program *programObject = context->getProgram(program);
3863 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003864
Jamie Madill78f41802014-08-25 15:47:55 -04003865 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003866 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003867 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003868 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003869 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003870 context->handleError(
3871 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003872 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003873 }
3874
Geoff Langf41d0ee2016-10-07 13:04:23 -04003875 if (length)
3876 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003877 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003878 }
3879
Jamie Madill0063c512014-08-25 15:47:53 -04003880 return true;
3881}
3882
He Yunchaoced53ae2016-11-29 15:00:51 +08003883bool ValidateGetnUniformfvEXT(Context *context,
3884 GLuint program,
3885 GLint location,
3886 GLsizei bufSize,
3887 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003888{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003889 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003890}
3891
He Yunchaoced53ae2016-11-29 15:00:51 +08003892bool ValidateGetnUniformivEXT(Context *context,
3893 GLuint program,
3894 GLint location,
3895 GLsizei bufSize,
3896 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003897{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003898 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3899}
3900
3901bool ValidateGetUniformfvRobustANGLE(Context *context,
3902 GLuint program,
3903 GLint location,
3904 GLsizei bufSize,
3905 GLsizei *length,
3906 GLfloat *params)
3907{
3908 if (!ValidateRobustEntryPoint(context, bufSize))
3909 {
3910 return false;
3911 }
3912
3913 // bufSize is validated in ValidateSizedGetUniform
3914 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3915}
3916
3917bool ValidateGetUniformivRobustANGLE(Context *context,
3918 GLuint program,
3919 GLint location,
3920 GLsizei bufSize,
3921 GLsizei *length,
3922 GLint *params)
3923{
3924 if (!ValidateRobustEntryPoint(context, bufSize))
3925 {
3926 return false;
3927 }
3928
3929 // bufSize is validated in ValidateSizedGetUniform
3930 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3931}
3932
3933bool ValidateGetUniformuivRobustANGLE(Context *context,
3934 GLuint program,
3935 GLint location,
3936 GLsizei bufSize,
3937 GLsizei *length,
3938 GLuint *params)
3939{
3940 if (!ValidateRobustEntryPoint(context, bufSize))
3941 {
3942 return false;
3943 }
3944
3945 if (context->getClientMajorVersion() < 3)
3946 {
3947 context->handleError(
3948 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3949 return false;
3950 }
3951
3952 // bufSize is validated in ValidateSizedGetUniform
3953 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003954}
3955
He Yunchaoced53ae2016-11-29 15:00:51 +08003956bool ValidateDiscardFramebufferBase(Context *context,
3957 GLenum target,
3958 GLsizei numAttachments,
3959 const GLenum *attachments,
3960 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003961{
3962 if (numAttachments < 0)
3963 {
Jamie Madill437fa652016-05-03 15:13:24 -04003964 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003965 return false;
3966 }
3967
3968 for (GLsizei i = 0; i < numAttachments; ++i)
3969 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003970 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003971 {
3972 if (defaultFramebuffer)
3973 {
Jamie Madill437fa652016-05-03 15:13:24 -04003974 context->handleError(Error(
3975 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003976 return false;
3977 }
3978
3979 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3980 {
Jamie Madill437fa652016-05-03 15:13:24 -04003981 context->handleError(Error(GL_INVALID_OPERATION,
3982 "Requested color attachment is greater than the maximum "
3983 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003984 return false;
3985 }
3986 }
3987 else
3988 {
3989 switch (attachments[i])
3990 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003991 case GL_DEPTH_ATTACHMENT:
3992 case GL_STENCIL_ATTACHMENT:
3993 case GL_DEPTH_STENCIL_ATTACHMENT:
3994 if (defaultFramebuffer)
3995 {
3996 context->handleError(
3997 Error(GL_INVALID_ENUM,
3998 "Invalid attachment when the default framebuffer is bound"));
3999 return false;
4000 }
4001 break;
4002 case GL_COLOR:
4003 case GL_DEPTH:
4004 case GL_STENCIL:
4005 if (!defaultFramebuffer)
4006 {
4007 context->handleError(
4008 Error(GL_INVALID_ENUM,
4009 "Invalid attachment when the default framebuffer is not bound"));
4010 return false;
4011 }
4012 break;
4013 default:
4014 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07004015 return false;
Austin Kinross08332632015-05-05 13:35:47 -07004016 }
4017 }
4018 }
4019
4020 return true;
4021}
4022
Austin Kinross6ee1e782015-05-29 17:05:37 -07004023bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
4024{
4025 // Note that debug marker calls must not set error state
4026
4027 if (length < 0)
4028 {
4029 return false;
4030 }
4031
4032 if (marker == nullptr)
4033 {
4034 return false;
4035 }
4036
4037 return true;
4038}
4039
4040bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
4041{
4042 // Note that debug marker calls must not set error state
4043
4044 if (length < 0)
4045 {
4046 return false;
4047 }
4048
4049 if (length > 0 && marker == nullptr)
4050 {
4051 return false;
4052 }
4053
4054 return true;
4055}
4056
Geoff Langdcab33b2015-07-21 13:03:16 -04004057bool ValidateEGLImageTargetTexture2DOES(Context *context,
4058 egl::Display *display,
4059 GLenum target,
4060 egl::Image *image)
4061{
Geoff Langa8406172015-07-21 16:53:39 -04004062 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4063 {
Jamie Madill437fa652016-05-03 15:13:24 -04004064 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004065 return false;
4066 }
4067
4068 switch (target)
4069 {
4070 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004071 if (!context->getExtensions().eglImage)
4072 {
4073 context->handleError(Error(
4074 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4075 }
4076 break;
4077
4078 case GL_TEXTURE_EXTERNAL_OES:
4079 if (!context->getExtensions().eglImageExternal)
4080 {
4081 context->handleError(Error(
4082 GL_INVALID_ENUM,
4083 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4084 }
Geoff Langa8406172015-07-21 16:53:39 -04004085 break;
4086
4087 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004088 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004089 return false;
4090 }
4091
4092 if (!display->isValidImage(image))
4093 {
Jamie Madill437fa652016-05-03 15:13:24 -04004094 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004095 return false;
4096 }
4097
4098 if (image->getSamples() > 0)
4099 {
Jamie Madill437fa652016-05-03 15:13:24 -04004100 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004101 "cannot create a 2D texture from a multisampled EGL image."));
4102 return false;
4103 }
4104
Jamie Madilla3944d42016-07-22 22:13:26 -04004105 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004106 if (!textureCaps.texturable)
4107 {
Jamie Madill437fa652016-05-03 15:13:24 -04004108 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004109 "EGL image internal format is not supported as a texture."));
4110 return false;
4111 }
4112
Geoff Langdcab33b2015-07-21 13:03:16 -04004113 return true;
4114}
4115
4116bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4117 egl::Display *display,
4118 GLenum target,
4119 egl::Image *image)
4120{
Geoff Langa8406172015-07-21 16:53:39 -04004121 if (!context->getExtensions().eglImage)
4122 {
Jamie Madill437fa652016-05-03 15:13:24 -04004123 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004124 return false;
4125 }
4126
4127 switch (target)
4128 {
4129 case GL_RENDERBUFFER:
4130 break;
4131
4132 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004133 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004134 return false;
4135 }
4136
4137 if (!display->isValidImage(image))
4138 {
Jamie Madill437fa652016-05-03 15:13:24 -04004139 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004140 return false;
4141 }
4142
Jamie Madilla3944d42016-07-22 22:13:26 -04004143 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004144 if (!textureCaps.renderable)
4145 {
Jamie Madill437fa652016-05-03 15:13:24 -04004146 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004147 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4148 return false;
4149 }
4150
Geoff Langdcab33b2015-07-21 13:03:16 -04004151 return true;
4152}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004153
4154bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4155{
Geoff Lang36167ab2015-12-07 10:27:14 -05004156 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004157 {
4158 // The default VAO should always exist
4159 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004160 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004161 return false;
4162 }
4163
4164 return true;
4165}
4166
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004167bool ValidateLinkProgram(Context *context, GLuint program)
4168{
4169 if (context->hasActiveTransformFeedback(program))
4170 {
4171 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004172 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004173 "Cannot link program while program is associated with an active "
4174 "transform feedback object."));
4175 return false;
4176 }
4177 return true;
4178}
4179
Geoff Langc5629752015-12-07 16:29:04 -05004180bool ValidateProgramBinaryBase(Context *context,
4181 GLuint program,
4182 GLenum binaryFormat,
4183 const void *binary,
4184 GLint length)
4185{
4186 Program *programObject = GetValidProgram(context, program);
4187 if (programObject == nullptr)
4188 {
4189 return false;
4190 }
4191
4192 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4193 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4194 programBinaryFormats.end())
4195 {
Jamie Madill437fa652016-05-03 15:13:24 -04004196 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004197 return false;
4198 }
4199
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004200 if (context->hasActiveTransformFeedback(program))
4201 {
4202 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004203 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004204 "Cannot change program binary while program is associated with "
4205 "an active transform feedback object."));
4206 return false;
4207 }
4208
Geoff Langc5629752015-12-07 16:29:04 -05004209 return true;
4210}
4211
4212bool ValidateGetProgramBinaryBase(Context *context,
4213 GLuint program,
4214 GLsizei bufSize,
4215 GLsizei *length,
4216 GLenum *binaryFormat,
4217 void *binary)
4218{
4219 Program *programObject = GetValidProgram(context, program);
4220 if (programObject == nullptr)
4221 {
4222 return false;
4223 }
4224
4225 if (!programObject->isLinked())
4226 {
Jamie Madill437fa652016-05-03 15:13:24 -04004227 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004228 return false;
4229 }
4230
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004231 if (context->getCaps().programBinaryFormats.empty())
4232 {
4233 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4234 return false;
4235 }
4236
Geoff Langc5629752015-12-07 16:29:04 -05004237 return true;
4238}
Jamie Madillc29968b2016-01-20 11:17:23 -05004239
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004240bool ValidateUseProgram(Context *context, GLuint program)
4241{
4242 if (program != 0)
4243 {
4244 Program *programObject = context->getProgram(program);
4245 if (!programObject)
4246 {
4247 // ES 3.1.0 section 7.3 page 72
4248 if (context->getShader(program))
4249 {
Jamie Madill437fa652016-05-03 15:13:24 -04004250 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004251 Error(GL_INVALID_OPERATION,
4252 "Attempted to use a single shader instead of a shader program."));
4253 return false;
4254 }
4255 else
4256 {
Jamie Madill437fa652016-05-03 15:13:24 -04004257 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004258 return false;
4259 }
4260 }
4261 if (!programObject->isLinked())
4262 {
Jamie Madill437fa652016-05-03 15:13:24 -04004263 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004264 return false;
4265 }
4266 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004267 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004268 {
4269 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004270 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004271 Error(GL_INVALID_OPERATION,
4272 "Cannot change active program while transform feedback is unpaused."));
4273 return false;
4274 }
4275
4276 return true;
4277}
4278
Jamie Madillc29968b2016-01-20 11:17:23 -05004279bool ValidateCopyTexImage2D(ValidationContext *context,
4280 GLenum target,
4281 GLint level,
4282 GLenum internalformat,
4283 GLint x,
4284 GLint y,
4285 GLsizei width,
4286 GLsizei height,
4287 GLint border)
4288{
Martin Radev1be913c2016-07-11 17:59:16 +03004289 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004290 {
4291 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4292 0, x, y, width, height, border);
4293 }
4294
Martin Radev1be913c2016-07-11 17:59:16 +03004295 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004296 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4297 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004298}
Jamie Madillc29968b2016-01-20 11:17:23 -05004299
4300bool ValidateFramebufferRenderbuffer(Context *context,
4301 GLenum target,
4302 GLenum attachment,
4303 GLenum renderbuffertarget,
4304 GLuint renderbuffer)
4305{
4306 if (!ValidFramebufferTarget(target) ||
4307 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4308 {
Jamie Madill437fa652016-05-03 15:13:24 -04004309 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004310 return false;
4311 }
4312
4313 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4314 renderbuffertarget, renderbuffer);
4315}
4316
4317bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4318{
4319 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4320 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4321 {
Jamie Madill437fa652016-05-03 15:13:24 -04004322 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004323 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4324 return false;
4325 }
4326
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004327 ASSERT(context->getGLState().getDrawFramebuffer());
4328 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004329 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4330
4331 // This should come first before the check for the default frame buffer
4332 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4333 // rather than INVALID_OPERATION
4334 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4335 {
4336 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4337
4338 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004339 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4340 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004341 {
4342 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004343 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4344 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4345 // 3.1 is still a bit ambiguous about the error, but future specs are
4346 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004347 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004348 return false;
4349 }
4350 else if (bufs[colorAttachment] >= maxColorAttachment)
4351 {
Jamie Madill437fa652016-05-03 15:13:24 -04004352 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004353 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004354 return false;
4355 }
4356 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4357 frameBufferId != 0)
4358 {
4359 // INVALID_OPERATION-GL is bound to buffer and ith argument
4360 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004361 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004362 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4363 return false;
4364 }
4365 }
4366
4367 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4368 // and n is not 1 or bufs is bound to value other than BACK and NONE
4369 if (frameBufferId == 0)
4370 {
4371 if (n != 1)
4372 {
Jamie Madill437fa652016-05-03 15:13:24 -04004373 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004374 "n must be 1 when GL is bound to the default framebuffer"));
4375 return false;
4376 }
4377
4378 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4379 {
Jamie Madill437fa652016-05-03 15:13:24 -04004380 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004381 GL_INVALID_OPERATION,
4382 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4383 return false;
4384 }
4385 }
4386
4387 return true;
4388}
4389
4390bool ValidateCopyTexSubImage2D(Context *context,
4391 GLenum target,
4392 GLint level,
4393 GLint xoffset,
4394 GLint yoffset,
4395 GLint x,
4396 GLint y,
4397 GLsizei width,
4398 GLsizei height)
4399{
Martin Radev1be913c2016-07-11 17:59:16 +03004400 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004401 {
4402 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4403 yoffset, x, y, width, height, 0);
4404 }
4405
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004406 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4407 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004408}
4409
Geoff Lang496c02d2016-10-20 11:38:11 -07004410bool ValidateGetBufferPointervBase(Context *context,
4411 GLenum target,
4412 GLenum pname,
4413 GLsizei *length,
4414 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004415{
Geoff Lang496c02d2016-10-20 11:38:11 -07004416 if (length)
4417 {
4418 *length = 0;
4419 }
4420
4421 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4422 {
4423 context->handleError(
4424 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004425 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004426 return false;
4427 }
4428
Olli Etuaho4f667482016-03-30 15:56:35 +03004429 if (!ValidBufferTarget(context, target))
4430 {
Jamie Madill437fa652016-05-03 15:13:24 -04004431 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004432 return false;
4433 }
4434
Geoff Lang496c02d2016-10-20 11:38:11 -07004435 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004436 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004437 case GL_BUFFER_MAP_POINTER:
4438 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004439
Geoff Lang496c02d2016-10-20 11:38:11 -07004440 default:
4441 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4442 return false;
4443 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004444
4445 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4446 // target bound to zero generate an INVALID_OPERATION error."
4447 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004448 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004449 {
Jamie Madill437fa652016-05-03 15:13:24 -04004450 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004451 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4452 return false;
4453 }
4454
Geoff Lang496c02d2016-10-20 11:38:11 -07004455 if (length)
4456 {
4457 *length = 1;
4458 }
4459
Olli Etuaho4f667482016-03-30 15:56:35 +03004460 return true;
4461}
4462
4463bool ValidateUnmapBufferBase(Context *context, GLenum target)
4464{
4465 if (!ValidBufferTarget(context, target))
4466 {
Jamie Madill437fa652016-05-03 15:13:24 -04004467 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004468 return false;
4469 }
4470
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004471 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004472
4473 if (buffer == nullptr || !buffer->isMapped())
4474 {
Jamie Madill437fa652016-05-03 15:13:24 -04004475 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004476 return false;
4477 }
4478
4479 return true;
4480}
4481
4482bool ValidateMapBufferRangeBase(Context *context,
4483 GLenum target,
4484 GLintptr offset,
4485 GLsizeiptr length,
4486 GLbitfield access)
4487{
4488 if (!ValidBufferTarget(context, target))
4489 {
Jamie Madill437fa652016-05-03 15:13:24 -04004490 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004491 return false;
4492 }
4493
4494 if (offset < 0 || length < 0)
4495 {
Jamie Madill437fa652016-05-03 15:13:24 -04004496 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004497 return false;
4498 }
4499
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004500 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004501
4502 if (!buffer)
4503 {
Jamie Madill437fa652016-05-03 15:13:24 -04004504 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004505 return false;
4506 }
4507
4508 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004509 CheckedNumeric<size_t> checkedOffset(offset);
4510 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004511
Jamie Madille2e406c2016-06-02 13:04:10 -04004512 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004513 {
Jamie Madill437fa652016-05-03 15:13:24 -04004514 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004515 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4516 return false;
4517 }
4518
4519 // Check for invalid bits in the mask
4520 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4521 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4522 GL_MAP_UNSYNCHRONIZED_BIT;
4523
4524 if (access & ~(allAccessBits))
4525 {
Jamie Madill437fa652016-05-03 15:13:24 -04004526 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004527 return false;
4528 }
4529
4530 if (length == 0)
4531 {
Jamie Madill437fa652016-05-03 15:13:24 -04004532 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004533 return false;
4534 }
4535
4536 if (buffer->isMapped())
4537 {
Jamie Madill437fa652016-05-03 15:13:24 -04004538 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004539 return false;
4540 }
4541
4542 // Check for invalid bit combinations
4543 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4544 {
Jamie Madill437fa652016-05-03 15:13:24 -04004545 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004546 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4547 return false;
4548 }
4549
4550 GLbitfield writeOnlyBits =
4551 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4552
4553 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4554 {
Jamie Madill437fa652016-05-03 15:13:24 -04004555 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004556 "Invalid access bits when mapping buffer for reading: 0x%X.",
4557 access));
4558 return false;
4559 }
4560
4561 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4562 {
Jamie Madill437fa652016-05-03 15:13:24 -04004563 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004564 GL_INVALID_OPERATION,
4565 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4566 return false;
4567 }
4568 return true;
4569}
4570
4571bool ValidateFlushMappedBufferRangeBase(Context *context,
4572 GLenum target,
4573 GLintptr offset,
4574 GLsizeiptr length)
4575{
4576 if (offset < 0 || length < 0)
4577 {
Jamie Madill437fa652016-05-03 15:13:24 -04004578 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004579 return false;
4580 }
4581
4582 if (!ValidBufferTarget(context, target))
4583 {
Jamie Madill437fa652016-05-03 15:13:24 -04004584 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004585 return false;
4586 }
4587
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004588 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004589
4590 if (buffer == nullptr)
4591 {
Jamie Madill437fa652016-05-03 15:13:24 -04004592 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004593 return false;
4594 }
4595
4596 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4597 {
Jamie Madill437fa652016-05-03 15:13:24 -04004598 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004599 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4600 return false;
4601 }
4602
4603 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004604 CheckedNumeric<size_t> checkedOffset(offset);
4605 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004606
Jamie Madille2e406c2016-06-02 13:04:10 -04004607 if (!checkedSize.IsValid() ||
4608 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004609 {
Jamie Madill437fa652016-05-03 15:13:24 -04004610 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004611 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4612 return false;
4613 }
4614
4615 return true;
4616}
4617
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004618bool ValidateGenerateMipmap(Context *context, GLenum target)
4619{
4620 if (!ValidTextureTarget(context, target))
4621 {
4622 context->handleError(Error(GL_INVALID_ENUM));
4623 return false;
4624 }
4625
4626 Texture *texture = context->getTargetTexture(target);
4627
4628 if (texture == nullptr)
4629 {
4630 context->handleError(Error(GL_INVALID_OPERATION));
4631 return false;
4632 }
4633
4634 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4635
4636 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4637 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4638 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4639 {
4640 context->handleError(Error(GL_INVALID_OPERATION));
4641 return false;
4642 }
4643
Jamie Madilla3944d42016-07-22 22:13:26 -04004644 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4645 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4646 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004647
4648 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4649 // unsized formats or that are color renderable and filterable. Since we do not track if
4650 // the texture was created with sized or unsized format (only sized formats are stored),
4651 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4652 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4653 // textures since they're the only texture format that can be created with unsized formats
4654 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4655 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004656 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4657 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004658 {
4659 context->handleError(Error(GL_INVALID_OPERATION));
4660 return false;
4661 }
4662
4663 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004664 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004665 {
4666 context->handleError(Error(GL_INVALID_OPERATION));
4667 return false;
4668 }
4669
4670 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004671 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004672 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4673 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4674 {
Geoff Lang55482a12016-11-21 16:54:01 -05004675 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004676 context->handleError(Error(GL_INVALID_OPERATION));
4677 return false;
4678 }
4679
4680 // Cube completeness check
4681 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4682 {
4683 context->handleError(Error(GL_INVALID_OPERATION));
4684 return false;
4685 }
4686
4687 return true;
4688}
4689
Olli Etuaho41997e72016-03-10 13:38:39 +02004690bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4691{
4692 return ValidateGenOrDelete(context, n);
4693}
4694
4695bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4696{
4697 return ValidateGenOrDelete(context, n);
4698}
4699
4700bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4701{
4702 return ValidateGenOrDelete(context, n);
4703}
4704
4705bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4706{
4707 return ValidateGenOrDelete(context, n);
4708}
4709
4710bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4711{
4712 return ValidateGenOrDelete(context, n);
4713}
4714
4715bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4716{
4717 return ValidateGenOrDelete(context, n);
4718}
4719
4720bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4721{
4722 return ValidateGenOrDelete(context, n);
4723}
4724
4725bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4726{
4727 return ValidateGenOrDelete(context, n);
4728}
4729
4730bool ValidateGenOrDelete(Context *context, GLint n)
4731{
4732 if (n < 0)
4733 {
Jamie Madill437fa652016-05-03 15:13:24 -04004734 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004735 return false;
4736 }
4737 return true;
4738}
4739
Geoff Langf41a7152016-09-19 15:11:17 -04004740bool ValidateEnable(Context *context, GLenum cap)
4741{
4742 if (!ValidCap(context, cap, false))
4743 {
4744 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4745 return false;
4746 }
4747
4748 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4749 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4750 {
4751 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4752 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4753
4754 // We also output an error message to the debugger window if tracing is active, so that
4755 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05004756 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04004757 return false;
4758 }
4759
4760 return true;
4761}
4762
4763bool ValidateDisable(Context *context, GLenum cap)
4764{
4765 if (!ValidCap(context, cap, false))
4766 {
4767 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4768 return false;
4769 }
4770
4771 return true;
4772}
4773
4774bool ValidateIsEnabled(Context *context, GLenum cap)
4775{
4776 if (!ValidCap(context, cap, true))
4777 {
4778 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4779 return false;
4780 }
4781
4782 return true;
4783}
4784
Geoff Langff5b2d52016-09-07 11:32:23 -04004785bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4786{
4787 if (!context->getExtensions().robustClientMemory)
4788 {
4789 context->handleError(
4790 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4791 return false;
4792 }
4793
4794 if (bufSize < 0)
4795 {
4796 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4797 return false;
4798 }
4799
4800 return true;
4801}
4802
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004803bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4804{
4805 if (bufSize < numParams)
4806 {
4807 context->handleError(Error(GL_INVALID_OPERATION,
4808 "%u parameters are required but %i were provided.", numParams,
4809 bufSize));
4810 return false;
4811 }
4812
4813 return true;
4814}
4815
Geoff Langff5b2d52016-09-07 11:32:23 -04004816bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4817 GLenum target,
4818 GLenum attachment,
4819 GLenum pname,
4820 GLsizei *numParams)
4821{
4822 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4823 *numParams = 1;
4824
4825 if (!ValidFramebufferTarget(target))
4826 {
4827 context->handleError(Error(GL_INVALID_ENUM));
4828 return false;
4829 }
4830
4831 int clientVersion = context->getClientMajorVersion();
4832
4833 switch (pname)
4834 {
4835 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4836 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4837 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4838 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4839 break;
4840
4841 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4842 if (clientVersion < 3 && !context->getExtensions().sRGB)
4843 {
4844 context->handleError(Error(GL_INVALID_ENUM));
4845 return false;
4846 }
4847 break;
4848
4849 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4850 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4851 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4852 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4853 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4854 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4855 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4856 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4857 if (clientVersion < 3)
4858 {
4859 context->handleError(Error(GL_INVALID_ENUM));
4860 return false;
4861 }
4862 break;
4863
4864 default:
4865 context->handleError(Error(GL_INVALID_ENUM));
4866 return false;
4867 }
4868
4869 // Determine if the attachment is a valid enum
4870 switch (attachment)
4871 {
4872 case GL_BACK:
4873 case GL_FRONT:
4874 case GL_DEPTH:
4875 case GL_STENCIL:
4876 case GL_DEPTH_STENCIL_ATTACHMENT:
4877 if (clientVersion < 3)
4878 {
4879 context->handleError(Error(GL_INVALID_ENUM));
4880 return false;
4881 }
4882 break;
4883
4884 case GL_DEPTH_ATTACHMENT:
4885 case GL_STENCIL_ATTACHMENT:
4886 break;
4887
4888 default:
4889 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4890 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4891 {
4892 context->handleError(Error(GL_INVALID_ENUM));
4893 return false;
4894 }
4895 break;
4896 }
4897
4898 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4899 ASSERT(framebuffer);
4900
4901 if (framebuffer->id() == 0)
4902 {
4903 if (clientVersion < 3)
4904 {
4905 context->handleError(Error(GL_INVALID_OPERATION));
4906 return false;
4907 }
4908
4909 switch (attachment)
4910 {
4911 case GL_BACK:
4912 case GL_DEPTH:
4913 case GL_STENCIL:
4914 break;
4915
4916 default:
4917 context->handleError(Error(GL_INVALID_OPERATION));
4918 return false;
4919 }
4920 }
4921 else
4922 {
4923 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4924 {
4925 // Valid attachment query
4926 }
4927 else
4928 {
4929 switch (attachment)
4930 {
4931 case GL_DEPTH_ATTACHMENT:
4932 case GL_STENCIL_ATTACHMENT:
4933 break;
4934
4935 case GL_DEPTH_STENCIL_ATTACHMENT:
4936 if (!framebuffer->hasValidDepthStencil())
4937 {
4938 context->handleError(Error(GL_INVALID_OPERATION));
4939 return false;
4940 }
4941 break;
4942
4943 default:
4944 context->handleError(Error(GL_INVALID_OPERATION));
4945 return false;
4946 }
4947 }
4948 }
4949
4950 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4951 if (attachmentObject)
4952 {
4953 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4954 attachmentObject->type() == GL_TEXTURE ||
4955 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4956
4957 switch (pname)
4958 {
4959 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4960 if (attachmentObject->type() != GL_RENDERBUFFER &&
4961 attachmentObject->type() != GL_TEXTURE)
4962 {
4963 context->handleError(Error(GL_INVALID_ENUM));
4964 return false;
4965 }
4966 break;
4967
4968 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4969 if (attachmentObject->type() != GL_TEXTURE)
4970 {
4971 context->handleError(Error(GL_INVALID_ENUM));
4972 return false;
4973 }
4974 break;
4975
4976 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4977 if (attachmentObject->type() != GL_TEXTURE)
4978 {
4979 context->handleError(Error(GL_INVALID_ENUM));
4980 return false;
4981 }
4982 break;
4983
4984 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4985 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4986 {
4987 context->handleError(Error(GL_INVALID_OPERATION));
4988 return false;
4989 }
4990 break;
4991
4992 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4993 if (attachmentObject->type() != GL_TEXTURE)
4994 {
4995 context->handleError(Error(GL_INVALID_ENUM));
4996 return false;
4997 }
4998 break;
4999
5000 default:
5001 break;
5002 }
5003 }
5004 else
5005 {
5006 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
5007 // is NONE, then querying any other pname will generate INVALID_ENUM.
5008
5009 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
5010 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
5011 // INVALID_OPERATION for all other pnames
5012
5013 switch (pname)
5014 {
5015 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5016 break;
5017
5018 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5019 if (clientVersion < 3)
5020 {
5021 context->handleError(Error(GL_INVALID_ENUM));
5022 return false;
5023 }
5024 break;
5025
5026 default:
5027 if (clientVersion < 3)
5028 {
5029 context->handleError(Error(GL_INVALID_ENUM));
5030 return false;
5031 }
5032 else
5033 {
5034 context->handleError(Error(GL_INVALID_OPERATION));
5035 return false;
5036 }
5037 }
5038 }
5039
5040 return true;
5041}
5042
5043bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5044 GLenum target,
5045 GLenum attachment,
5046 GLenum pname,
5047 GLsizei bufSize,
5048 GLsizei *numParams)
5049{
5050 if (!ValidateRobustEntryPoint(context, bufSize))
5051 {
5052 return false;
5053 }
5054
5055 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5056 {
5057 return false;
5058 }
5059
5060 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5061 {
5062 return false;
5063 }
5064
5065 return true;
5066}
5067
5068bool ValidateGetBufferParameteriv(ValidationContext *context,
5069 GLenum target,
5070 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005071 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005072{
Geoff Langebebe1c2016-10-14 12:01:31 -04005073 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005074}
5075
5076bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5077 GLenum target,
5078 GLenum pname,
5079 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005080 GLsizei *length,
5081 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005082{
5083 if (!ValidateRobustEntryPoint(context, bufSize))
5084 {
5085 return false;
5086 }
5087
Geoff Langebebe1c2016-10-14 12:01:31 -04005088 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005089 {
5090 return false;
5091 }
5092
Geoff Langebebe1c2016-10-14 12:01:31 -04005093 if (!ValidateRobustBufferSize(context, bufSize, *length))
5094 {
5095 return false;
5096 }
5097
5098 return true;
5099}
5100
5101bool ValidateGetBufferParameteri64v(ValidationContext *context,
5102 GLenum target,
5103 GLenum pname,
5104 GLint64 *params)
5105{
5106 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5107}
5108
5109bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5110 GLenum target,
5111 GLenum pname,
5112 GLsizei bufSize,
5113 GLsizei *length,
5114 GLint64 *params)
5115{
5116 if (!ValidateRobustEntryPoint(context, bufSize))
5117 {
5118 return false;
5119 }
5120
5121 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5122 {
5123 return false;
5124 }
5125
5126 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005127 {
5128 return false;
5129 }
5130
5131 return true;
5132}
5133
5134bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5135{
5136 // Currently, all GetProgramiv queries return 1 parameter
5137 *numParams = 1;
5138
5139 Program *programObject = GetValidProgram(context, program);
5140 if (!programObject)
5141 {
5142 return false;
5143 }
5144
5145 switch (pname)
5146 {
5147 case GL_DELETE_STATUS:
5148 case GL_LINK_STATUS:
5149 case GL_VALIDATE_STATUS:
5150 case GL_INFO_LOG_LENGTH:
5151 case GL_ATTACHED_SHADERS:
5152 case GL_ACTIVE_ATTRIBUTES:
5153 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5154 case GL_ACTIVE_UNIFORMS:
5155 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5156 break;
5157
5158 case GL_PROGRAM_BINARY_LENGTH:
5159 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5160 {
5161 context->handleError(Error(GL_INVALID_ENUM,
5162 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5163 "GL_OES_get_program_binary or ES 3.0."));
5164 return false;
5165 }
5166 break;
5167
5168 case GL_ACTIVE_UNIFORM_BLOCKS:
5169 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5170 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5171 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5172 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5173 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5174 if (context->getClientMajorVersion() < 3)
5175 {
5176 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5177 return false;
5178 }
5179 break;
5180
5181 default:
5182 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5183 return false;
5184 }
5185
5186 return true;
5187}
5188
5189bool ValidateGetProgramivRobustANGLE(Context *context,
5190 GLuint program,
5191 GLenum pname,
5192 GLsizei bufSize,
5193 GLsizei *numParams)
5194{
5195 if (!ValidateRobustEntryPoint(context, bufSize))
5196 {
5197 return false;
5198 }
5199
5200 if (!ValidateGetProgramiv(context, program, pname, numParams))
5201 {
5202 return false;
5203 }
5204
5205 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5206 {
5207 return false;
5208 }
5209
5210 return true;
5211}
5212
Geoff Lang740d9022016-10-07 11:20:52 -04005213bool ValidateGetRenderbufferParameteriv(Context *context,
5214 GLenum target,
5215 GLenum pname,
5216 GLint *params)
5217{
5218 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5219}
5220
5221bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5222 GLenum target,
5223 GLenum pname,
5224 GLsizei bufSize,
5225 GLsizei *length,
5226 GLint *params)
5227{
5228 if (!ValidateRobustEntryPoint(context, bufSize))
5229 {
5230 return false;
5231 }
5232
5233 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5234 {
5235 return false;
5236 }
5237
5238 if (!ValidateRobustBufferSize(context, bufSize, *length))
5239 {
5240 return false;
5241 }
5242
5243 return true;
5244}
5245
Geoff Langd7d0ed32016-10-07 11:33:51 -04005246bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5247{
5248 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5249}
5250
5251bool ValidateGetShaderivRobustANGLE(Context *context,
5252 GLuint shader,
5253 GLenum pname,
5254 GLsizei bufSize,
5255 GLsizei *length,
5256 GLint *params)
5257{
5258 if (!ValidateRobustEntryPoint(context, bufSize))
5259 {
5260 return false;
5261 }
5262
5263 if (!ValidateGetShaderivBase(context, shader, pname, length))
5264 {
5265 return false;
5266 }
5267
5268 if (!ValidateRobustBufferSize(context, bufSize, *length))
5269 {
5270 return false;
5271 }
5272
5273 return true;
5274}
5275
Geoff Langc1984ed2016-10-07 12:41:00 -04005276bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5277{
5278 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5279}
5280
5281bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5282 GLenum target,
5283 GLenum pname,
5284 GLsizei bufSize,
5285 GLsizei *length,
5286 GLfloat *params)
5287{
5288 if (!ValidateRobustEntryPoint(context, bufSize))
5289 {
5290 return false;
5291 }
5292
5293 if (!ValidateGetTexParameterBase(context, target, pname, length))
5294 {
5295 return false;
5296 }
5297
5298 if (!ValidateRobustBufferSize(context, bufSize, *length))
5299 {
5300 return false;
5301 }
5302
5303 return true;
5304}
5305
5306bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5307{
5308 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5309}
5310
5311bool ValidateGetTexParameterivRobustANGLE(Context *context,
5312 GLenum target,
5313 GLenum pname,
5314 GLsizei bufSize,
5315 GLsizei *length,
5316 GLint *params)
5317{
5318 if (!ValidateRobustEntryPoint(context, bufSize))
5319 {
5320 return false;
5321 }
5322
5323 if (!ValidateGetTexParameterBase(context, target, pname, length))
5324 {
5325 return false;
5326 }
5327
5328 if (!ValidateRobustBufferSize(context, bufSize, *length))
5329 {
5330 return false;
5331 }
5332
5333 return true;
5334}
5335
5336bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5337{
5338 return ValidateTexParameterBase(context, target, pname, -1, &param);
5339}
5340
5341bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5342{
5343 return ValidateTexParameterBase(context, target, pname, -1, params);
5344}
5345
5346bool ValidateTexParameterfvRobustANGLE(Context *context,
5347 GLenum target,
5348 GLenum pname,
5349 GLsizei bufSize,
5350 const GLfloat *params)
5351{
5352 if (!ValidateRobustEntryPoint(context, bufSize))
5353 {
5354 return false;
5355 }
5356
5357 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5358}
5359
5360bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5361{
5362 return ValidateTexParameterBase(context, target, pname, -1, &param);
5363}
5364
5365bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5366{
5367 return ValidateTexParameterBase(context, target, pname, -1, params);
5368}
5369
5370bool ValidateTexParameterivRobustANGLE(Context *context,
5371 GLenum target,
5372 GLenum pname,
5373 GLsizei bufSize,
5374 const GLint *params)
5375{
5376 if (!ValidateRobustEntryPoint(context, bufSize))
5377 {
5378 return false;
5379 }
5380
5381 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5382}
5383
5384bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5385{
5386 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5387}
5388
5389bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5390 GLuint sampler,
5391 GLenum pname,
5392 GLuint bufSize,
5393 GLsizei *length,
5394 GLfloat *params)
5395{
5396 if (!ValidateRobustEntryPoint(context, bufSize))
5397 {
5398 return false;
5399 }
5400
5401 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5402 {
5403 return false;
5404 }
5405
5406 if (!ValidateRobustBufferSize(context, bufSize, *length))
5407 {
5408 return false;
5409 }
5410
5411 return true;
5412}
5413
5414bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5415{
5416 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5417}
5418
5419bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5420 GLuint sampler,
5421 GLenum pname,
5422 GLuint bufSize,
5423 GLsizei *length,
5424 GLint *params)
5425{
5426 if (!ValidateRobustEntryPoint(context, bufSize))
5427 {
5428 return false;
5429 }
5430
5431 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5432 {
5433 return false;
5434 }
5435
5436 if (!ValidateRobustBufferSize(context, bufSize, *length))
5437 {
5438 return false;
5439 }
5440
5441 return true;
5442}
5443
5444bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5445{
5446 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5447}
5448
5449bool ValidateSamplerParameterfv(Context *context,
5450 GLuint sampler,
5451 GLenum pname,
5452 const GLfloat *params)
5453{
5454 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5455}
5456
5457bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5458 GLuint sampler,
5459 GLenum pname,
5460 GLsizei bufSize,
5461 const GLfloat *params)
5462{
5463 if (!ValidateRobustEntryPoint(context, bufSize))
5464 {
5465 return false;
5466 }
5467
5468 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5469}
5470
5471bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5472{
5473 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5474}
5475
5476bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5477{
5478 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5479}
5480
5481bool ValidateSamplerParameterivRobustANGLE(Context *context,
5482 GLuint sampler,
5483 GLenum pname,
5484 GLsizei bufSize,
5485 const GLint *params)
5486{
5487 if (!ValidateRobustEntryPoint(context, bufSize))
5488 {
5489 return false;
5490 }
5491
5492 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5493}
5494
Geoff Lang0b031062016-10-13 14:30:04 -04005495bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5496{
5497 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5498}
5499
5500bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5501 GLuint index,
5502 GLenum pname,
5503 GLsizei bufSize,
5504 GLsizei *length,
5505 GLfloat *params)
5506{
5507 if (!ValidateRobustEntryPoint(context, bufSize))
5508 {
5509 return false;
5510 }
5511
5512 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5513 {
5514 return false;
5515 }
5516
5517 if (!ValidateRobustBufferSize(context, bufSize, *length))
5518 {
5519 return false;
5520 }
5521
5522 return true;
5523}
5524
5525bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5526{
5527 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5528}
5529
5530bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5531 GLuint index,
5532 GLenum pname,
5533 GLsizei bufSize,
5534 GLsizei *length,
5535 GLint *params)
5536{
5537 if (!ValidateRobustEntryPoint(context, bufSize))
5538 {
5539 return false;
5540 }
5541
5542 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5543 {
5544 return false;
5545 }
5546
5547 if (!ValidateRobustBufferSize(context, bufSize, *length))
5548 {
5549 return false;
5550 }
5551
5552 return true;
5553}
5554
5555bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5556{
5557 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5558}
5559
5560bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5561 GLuint index,
5562 GLenum pname,
5563 GLsizei bufSize,
5564 GLsizei *length,
5565 void **pointer)
5566{
5567 if (!ValidateRobustEntryPoint(context, bufSize))
5568 {
5569 return false;
5570 }
5571
5572 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5573 {
5574 return false;
5575 }
5576
5577 if (!ValidateRobustBufferSize(context, bufSize, *length))
5578 {
5579 return false;
5580 }
5581
5582 return true;
5583}
5584
5585bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5586{
5587 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5588}
5589
5590bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5591 GLuint index,
5592 GLenum pname,
5593 GLsizei bufSize,
5594 GLsizei *length,
5595 GLint *params)
5596{
5597 if (!ValidateRobustEntryPoint(context, bufSize))
5598 {
5599 return false;
5600 }
5601
5602 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5603 {
5604 return false;
5605 }
5606
5607 if (!ValidateRobustBufferSize(context, bufSize, *length))
5608 {
5609 return false;
5610 }
5611
5612 return true;
5613}
5614
5615bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5616{
5617 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5618}
5619
5620bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5621 GLuint index,
5622 GLenum pname,
5623 GLsizei bufSize,
5624 GLsizei *length,
5625 GLuint *params)
5626{
5627 if (!ValidateRobustEntryPoint(context, bufSize))
5628 {
5629 return false;
5630 }
5631
5632 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5633 {
5634 return false;
5635 }
5636
5637 if (!ValidateRobustBufferSize(context, bufSize, *length))
5638 {
5639 return false;
5640 }
5641
5642 return true;
5643}
5644
Geoff Lang6899b872016-10-14 11:30:13 -04005645bool ValidateGetActiveUniformBlockiv(Context *context,
5646 GLuint program,
5647 GLuint uniformBlockIndex,
5648 GLenum pname,
5649 GLint *params)
5650{
5651 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5652}
5653
5654bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5655 GLuint program,
5656 GLuint uniformBlockIndex,
5657 GLenum pname,
5658 GLsizei bufSize,
5659 GLsizei *length,
5660 GLint *params)
5661{
5662 if (!ValidateRobustEntryPoint(context, bufSize))
5663 {
5664 return false;
5665 }
5666
5667 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5668 {
5669 return false;
5670 }
5671
5672 if (!ValidateRobustBufferSize(context, bufSize, *length))
5673 {
5674 return false;
5675 }
5676
5677 return true;
5678}
5679
Geoff Lang0a9661f2016-10-20 10:59:20 -07005680bool ValidateGetInternalFormativ(Context *context,
5681 GLenum target,
5682 GLenum internalformat,
5683 GLenum pname,
5684 GLsizei bufSize,
5685 GLint *params)
5686{
5687 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5688 nullptr);
5689}
5690
5691bool ValidateGetInternalFormativRobustANGLE(Context *context,
5692 GLenum target,
5693 GLenum internalformat,
5694 GLenum pname,
5695 GLsizei bufSize,
5696 GLsizei *length,
5697 GLint *params)
5698{
5699 if (!ValidateRobustEntryPoint(context, bufSize))
5700 {
5701 return false;
5702 }
5703
5704 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5705 {
5706 return false;
5707 }
5708
5709 if (!ValidateRobustBufferSize(context, bufSize, *length))
5710 {
5711 return false;
5712 }
5713
5714 return true;
5715}
5716
Jamie Madillc29968b2016-01-20 11:17:23 -05005717} // namespace gl