blob: 505b903c93c2730c3bf19fc46ea7f9d109b33972 [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 Henigmana98a6472017-02-02 21:38:32 -05001420bool ValidateUniform1ivValue(gl::Context *context,
1421 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 {
1435 // TODO(fjhenigman): check values against GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
1436 return true;
1437 }
1438
1439 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1440 return false;
1441}
1442
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001443bool ValidateUniformValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1444{
1445 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -05001446 // Do the cheaper test first, for a little extra speed.
1447 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05001448 {
1449 return true;
1450 }
1451
1452 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1453 return false;
1454}
1455
1456bool ValidateUniformMatrixValue(gl::Context *context, GLenum valueType, GLenum uniformType)
1457{
1458 // Check that the value type is compatible with uniform type.
1459 if (valueType == uniformType)
1460 {
1461 return true;
1462 }
1463
1464 context->handleError(Error(GL_INVALID_OPERATION, "wrong type of value for uniform"));
1465 return false;
1466}
1467
Geoff Langf41a7152016-09-19 15:11:17 -04001468} // anonymous namespace
1469
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001470bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001471{
Jamie Madilld7460c72014-01-21 16:38:14 -05001472 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001473 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001474 case GL_TEXTURE_2D:
1475 case GL_TEXTURE_CUBE_MAP:
1476 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001477
He Yunchaoced53ae2016-11-29 15:00:51 +08001478 case GL_TEXTURE_3D:
1479 case GL_TEXTURE_2D_ARRAY:
1480 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001481
He Yunchaoced53ae2016-11-29 15:00:51 +08001482 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001483 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001484
He Yunchaoced53ae2016-11-29 15:00:51 +08001485 default:
1486 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001487 }
Jamie Madill35d15012013-10-07 10:46:37 -04001488}
1489
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001490bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1491{
1492 switch (target)
1493 {
1494 case GL_TEXTURE_2D:
1495 case GL_TEXTURE_CUBE_MAP:
1496 return true;
1497
1498 default:
1499 return false;
1500 }
1501}
1502
1503bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1504{
1505 switch (target)
1506 {
1507 case GL_TEXTURE_3D:
1508 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001509 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001510
1511 default:
1512 return false;
1513 }
1514}
1515
Ian Ewellbda75592016-04-18 17:25:54 -04001516// Most texture GL calls are not compatible with external textures, so we have a separate validation
1517// function for use in the GL calls that do
1518bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1519{
1520 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1521 (context->getExtensions().eglImageExternal ||
1522 context->getExtensions().eglStreamConsumerExternal);
1523}
1524
Shannon Woods4dfed832014-03-17 20:03:39 -04001525// This function differs from ValidTextureTarget in that the target must be
1526// usable as the destination of a 2D operation-- so a cube face is valid, but
1527// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001528// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001529bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001530{
1531 switch (target)
1532 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001533 case GL_TEXTURE_2D:
1534 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1535 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1536 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1537 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1538 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1539 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1540 return true;
1541 default:
1542 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001543 }
1544}
1545
1546bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1547{
1548 switch (target)
1549 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001550 case GL_TEXTURE_3D:
1551 case GL_TEXTURE_2D_ARRAY:
1552 return true;
1553 default:
1554 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001555 }
1556}
1557
He Yunchao11b038b2016-11-22 21:24:04 +08001558bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1559{
1560 switch (target)
1561 {
1562 case GL_TEXTURE_2D:
1563 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1564 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1565 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1566 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1567 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1568 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1569 case GL_TEXTURE_3D:
1570 case GL_TEXTURE_2D_ARRAY:
1571 case GL_TEXTURE_2D_MULTISAMPLE:
1572 return true;
1573 default:
1574 return false;
1575 }
1576}
1577
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001578bool ValidFramebufferTarget(GLenum target)
1579{
He Yunchaoced53ae2016-11-29 15:00:51 +08001580 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1581 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001582 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001583
1584 switch (target)
1585 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001586 case GL_FRAMEBUFFER:
1587 return true;
1588 case GL_READ_FRAMEBUFFER:
1589 return true;
1590 case GL_DRAW_FRAMEBUFFER:
1591 return true;
1592 default:
1593 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001594 }
1595}
1596
Jamie Madill29639852016-09-02 15:00:09 -04001597bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001598{
1599 switch (target)
1600 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001601 case GL_ARRAY_BUFFER:
1602 case GL_ELEMENT_ARRAY_BUFFER:
1603 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001604
He Yunchaoced53ae2016-11-29 15:00:51 +08001605 case GL_PIXEL_PACK_BUFFER:
1606 case GL_PIXEL_UNPACK_BUFFER:
1607 return (context->getExtensions().pixelBufferObject ||
1608 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001609
He Yunchaoced53ae2016-11-29 15:00:51 +08001610 case GL_COPY_READ_BUFFER:
1611 case GL_COPY_WRITE_BUFFER:
1612 case GL_TRANSFORM_FEEDBACK_BUFFER:
1613 case GL_UNIFORM_BUFFER:
1614 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001615
He Yunchaoced53ae2016-11-29 15:00:51 +08001616 case GL_ATOMIC_COUNTER_BUFFER:
1617 case GL_SHADER_STORAGE_BUFFER:
1618 case GL_DRAW_INDIRECT_BUFFER:
1619 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001620 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001621
He Yunchaoced53ae2016-11-29 15:00:51 +08001622 default:
1623 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001624 }
1625}
1626
Jamie Madillc29968b2016-01-20 11:17:23 -05001627bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001628{
Jamie Madillc29968b2016-01-20 11:17:23 -05001629 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001630 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001631 switch (target)
1632 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001633 case GL_TEXTURE_2D:
1634 maxDimension = caps.max2DTextureSize;
1635 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001636 case GL_TEXTURE_CUBE_MAP:
1637 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1638 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1639 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1640 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1641 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1642 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1643 maxDimension = caps.maxCubeMapTextureSize;
1644 break;
1645 case GL_TEXTURE_3D:
1646 maxDimension = caps.max3DTextureSize;
1647 break;
1648 case GL_TEXTURE_2D_ARRAY:
1649 maxDimension = caps.max2DTextureSize;
1650 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001651 case GL_TEXTURE_2D_MULTISAMPLE:
1652 maxDimension = caps.max2DTextureSize;
1653 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001654 default:
1655 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001656 }
1657
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001658 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001659}
1660
Geoff Langcc507aa2016-12-12 10:09:52 -05001661bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001662 GLenum target,
1663 GLint level,
1664 GLsizei width,
1665 GLsizei height,
1666 GLsizei depth,
1667 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001668{
1669 if (level < 0 || width < 0 || height < 0 || depth < 0)
1670 {
1671 return false;
1672 }
1673
Austin Kinross08528e12015-10-07 16:24:40 -07001674 // TexSubImage parameters can be NPOT without textureNPOT extension,
1675 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001676 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001677 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001678 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001679 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001680 {
1681 return false;
1682 }
1683
1684 if (!ValidMipLevel(context, target, level))
1685 {
1686 return false;
1687 }
1688
1689 return true;
1690}
1691
Geoff Lang0d8b7242015-09-09 14:56:53 -04001692bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1693{
1694 // List of compressed format that require that the texture size is smaller than or a multiple of
1695 // the compressed block size.
1696 switch (internalFormat)
1697 {
1698 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1699 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1700 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1701 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001702 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001703 return true;
1704
1705 default:
1706 return false;
1707 }
1708}
1709
Jamie Madillc29968b2016-01-20 11:17:23 -05001710bool ValidCompressedImageSize(const ValidationContext *context,
1711 GLenum internalFormat,
1712 GLsizei width,
1713 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001714{
Geoff Lang5d601382014-07-22 15:14:06 -04001715 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1716 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001717 {
1718 return false;
1719 }
1720
Geoff Lang0d8b7242015-09-09 14:56:53 -04001721 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001722 {
1723 return false;
1724 }
1725
Geoff Lang0d8b7242015-09-09 14:56:53 -04001726 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1727 {
1728 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1729 width % formatInfo.compressedBlockWidth != 0) ||
1730 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1731 height % formatInfo.compressedBlockHeight != 0))
1732 {
1733 return false;
1734 }
1735 }
1736
Geoff Langd4f180b2013-09-24 13:57:44 -04001737 return true;
1738}
1739
Geoff Langff5b2d52016-09-07 11:32:23 -04001740bool ValidImageDataSize(ValidationContext *context,
1741 GLenum textureTarget,
1742 GLsizei width,
1743 GLsizei height,
1744 GLsizei depth,
1745 GLenum internalFormat,
1746 GLenum type,
1747 const GLvoid *pixels,
1748 GLsizei imageSize)
1749{
1750 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1751 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1752 {
1753 // Checks are not required
1754 return true;
1755 }
1756
1757 // ...the data would be unpacked from the buffer object such that the memory reads required
1758 // would exceed the data store size.
1759 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1760 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1761 const gl::Extents size(width, height, depth);
1762 const auto &unpack = context->getGLState().getUnpackState();
1763
1764 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1765 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1766 if (endByteOrErr.isError())
1767 {
1768 context->handleError(endByteOrErr.getError());
1769 return false;
1770 }
1771
1772 GLuint endByte = endByteOrErr.getResult();
1773
1774 if (pixelUnpackBuffer)
1775 {
1776 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1777 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1778 checkedEndByte += checkedOffset;
1779
1780 if (!checkedEndByte.IsValid() ||
1781 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1782 {
1783 // Overflow past the end of the buffer
1784 context->handleError(Error(GL_INVALID_OPERATION));
1785 return false;
1786 }
1787 }
1788 else
1789 {
1790 ASSERT(imageSize >= 0);
1791 if (pixels == nullptr && imageSize != 0)
1792 {
1793 context->handleError(
1794 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001795 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001796 }
1797
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001798 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001799 {
1800 context->handleError(
1801 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1802 return false;
1803 }
1804 }
1805
1806 return true;
1807}
1808
Geoff Lang37dde692014-01-31 16:34:54 -05001809bool ValidQueryType(const Context *context, GLenum queryType)
1810{
He Yunchaoced53ae2016-11-29 15:00:51 +08001811 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1812 "GL extension enums not equal.");
1813 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1814 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001815
1816 switch (queryType)
1817 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001818 case GL_ANY_SAMPLES_PASSED:
1819 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1820 return true;
1821 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1822 return (context->getClientMajorVersion() >= 3);
1823 case GL_TIME_ELAPSED_EXT:
1824 return context->getExtensions().disjointTimerQuery;
1825 case GL_COMMANDS_COMPLETED_CHROMIUM:
1826 return context->getExtensions().syncQuery;
1827 default:
1828 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001829 }
1830}
1831
Jamie Madillef300b12016-10-07 15:12:09 -04001832Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001833{
He Yunchaoced53ae2016-11-29 15:00:51 +08001834 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1835 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1836 // or program object and INVALID_OPERATION if the provided name identifies an object
1837 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001838
Dian Xiang769769a2015-09-09 15:20:08 -07001839 Program *validProgram = context->getProgram(id);
1840
1841 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001842 {
Dian Xiang769769a2015-09-09 15:20:08 -07001843 if (context->getShader(id))
1844 {
Jamie Madill437fa652016-05-03 15:13:24 -04001845 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001846 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1847 }
1848 else
1849 {
Jamie Madill437fa652016-05-03 15:13:24 -04001850 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001851 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001852 }
Dian Xiang769769a2015-09-09 15:20:08 -07001853
1854 return validProgram;
1855}
1856
Jamie Madillef300b12016-10-07 15:12:09 -04001857Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001858{
1859 // See ValidProgram for spec details.
1860
1861 Shader *validShader = context->getShader(id);
1862
1863 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001864 {
Dian Xiang769769a2015-09-09 15:20:08 -07001865 if (context->getProgram(id))
1866 {
Jamie Madill437fa652016-05-03 15:13:24 -04001867 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001868 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1869 }
1870 else
1871 {
Jamie Madill437fa652016-05-03 15:13:24 -04001872 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001873 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001874 }
Dian Xiang769769a2015-09-09 15:20:08 -07001875
1876 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001877}
1878
Geoff Langb1196682014-07-23 13:47:29 -04001879bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001880{
1881 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1882 {
1883 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1884
Geoff Langaae65a42014-05-26 12:43:44 -04001885 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001886 {
Jamie Madill437fa652016-05-03 15:13:24 -04001887 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001888 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001889 }
1890 }
1891 else
1892 {
1893 switch (attachment)
1894 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001895 case GL_DEPTH_ATTACHMENT:
1896 case GL_STENCIL_ATTACHMENT:
1897 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001898
He Yunchaoced53ae2016-11-29 15:00:51 +08001899 case GL_DEPTH_STENCIL_ATTACHMENT:
1900 if (!context->getExtensions().webglCompatibility &&
1901 context->getClientMajorVersion() < 3)
1902 {
1903 context->handleError(Error(GL_INVALID_ENUM));
1904 return false;
1905 }
1906 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001907
He Yunchaoced53ae2016-11-29 15:00:51 +08001908 default:
1909 context->handleError(Error(GL_INVALID_ENUM));
1910 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001911 }
1912 }
1913
1914 return true;
1915}
1916
He Yunchaoced53ae2016-11-29 15:00:51 +08001917bool ValidateRenderbufferStorageParametersBase(gl::Context *context,
1918 GLenum target,
1919 GLsizei samples,
1920 GLenum internalformat,
1921 GLsizei width,
1922 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001923{
1924 switch (target)
1925 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001926 case GL_RENDERBUFFER:
1927 break;
1928 default:
1929 context->handleError(Error(GL_INVALID_ENUM));
1930 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001931 }
1932
1933 if (width < 0 || height < 0 || samples < 0)
1934 {
Jamie Madill437fa652016-05-03 15:13:24 -04001935 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001936 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001937 }
1938
Geoff Langd87878e2014-09-19 15:42:59 -04001939 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1940 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001941 {
Jamie Madill437fa652016-05-03 15:13:24 -04001942 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001943 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001944 }
1945
1946 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1947 // 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 -08001948 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001949 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001950 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001951 {
Jamie Madill437fa652016-05-03 15:13:24 -04001952 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001953 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001954 }
1955
Geoff Langaae65a42014-05-26 12:43:44 -04001956 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001957 {
Jamie Madill437fa652016-05-03 15:13:24 -04001958 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001959 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001960 }
1961
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001962 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001963 if (handle == 0)
1964 {
Jamie Madill437fa652016-05-03 15:13:24 -04001965 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001966 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001967 }
1968
1969 return true;
1970}
1971
He Yunchaoced53ae2016-11-29 15:00:51 +08001972bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context,
1973 GLenum target,
1974 GLsizei samples,
1975 GLenum internalformat,
1976 GLsizei width,
1977 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -08001978{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001979 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001980
1981 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001982 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001983 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001984 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001985 {
Jamie Madill437fa652016-05-03 15:13:24 -04001986 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001987 return false;
1988 }
1989
1990 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1991 // the specified storage. This is different than ES 3.0 in which a sample number higher
1992 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001993 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001994 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001995 {
Geoff Langa4903b72015-03-02 16:02:48 -08001996 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1997 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1998 {
Jamie Madill437fa652016-05-03 15:13:24 -04001999 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08002000 return false;
2001 }
Corentin Walleze0902642014-11-04 12:32:15 -08002002 }
2003
He Yunchaoced53ae2016-11-29 15:00:51 +08002004 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
2005 width, height);
Corentin Walleze0902642014-11-04 12:32:15 -08002006}
2007
He Yunchaoced53ae2016-11-29 15:00:51 +08002008bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
2009 GLenum target,
2010 GLenum attachment,
2011 GLenum renderbuffertarget,
2012 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002013{
Shannon Woods1da3cf62014-06-27 15:32:23 -04002014 if (!ValidFramebufferTarget(target))
2015 {
Jamie Madill437fa652016-05-03 15:13:24 -04002016 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002017 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04002018 }
2019
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002020 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002021
Jamie Madill84115c92015-04-23 15:00:07 -04002022 ASSERT(framebuffer);
2023 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002024 {
Jamie Madill437fa652016-05-03 15:13:24 -04002025 context->handleError(
2026 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04002027 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002028 }
2029
Jamie Madillb4472272014-07-03 10:38:55 -04002030 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002031 {
Jamie Madillb4472272014-07-03 10:38:55 -04002032 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002033 }
2034
Jamie Madillab9d82c2014-01-21 16:38:14 -05002035 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
2036 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
2037 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
2038 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
2039 if (renderbuffer != 0)
2040 {
2041 if (!context->getRenderbuffer(renderbuffer))
2042 {
Jamie Madill437fa652016-05-03 15:13:24 -04002043 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002044 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05002045 }
2046 }
2047
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05002048 return true;
2049}
2050
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002051bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002052 GLint srcX0,
2053 GLint srcY0,
2054 GLint srcX1,
2055 GLint srcY1,
2056 GLint dstX0,
2057 GLint dstY0,
2058 GLint dstX1,
2059 GLint dstY1,
2060 GLbitfield mask,
2061 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002062{
2063 switch (filter)
2064 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002065 case GL_NEAREST:
2066 break;
2067 case GL_LINEAR:
2068 break;
2069 default:
2070 context->handleError(Error(GL_INVALID_ENUM));
2071 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002072 }
2073
2074 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
2075 {
Jamie Madill437fa652016-05-03 15:13:24 -04002076 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002077 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002078 }
2079
2080 if (mask == 0)
2081 {
2082 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
2083 // buffers are copied.
2084 return false;
2085 }
2086
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002087 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
2088 // color buffer, leaving only nearest being unfiltered from above
2089 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
2090 {
Jamie Madill437fa652016-05-03 15:13:24 -04002091 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002092 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002093 }
2094
Jamie Madill51f40ec2016-06-15 14:06:00 -04002095 const auto &glState = context->getGLState();
2096 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
2097 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05002098
2099 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002100 {
Jamie Madill437fa652016-05-03 15:13:24 -04002101 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002102 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002103 }
2104
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002105 if (readFramebuffer->id() == drawFramebuffer->id())
2106 {
2107 context->handleError(Error(GL_INVALID_OPERATION));
2108 return false;
2109 }
2110
Jamie Madill51f40ec2016-06-15 14:06:00 -04002111 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002112 {
Jamie Madill437fa652016-05-03 15:13:24 -04002113 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002114 return false;
2115 }
2116
Jamie Madill51f40ec2016-06-15 14:06:00 -04002117 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002118 {
Jamie Madill437fa652016-05-03 15:13:24 -04002119 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002120 return false;
2121 }
2122
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002123 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002124 {
Jamie Madill437fa652016-05-03 15:13:24 -04002125 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002126 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002127 }
2128
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002129 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2130
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002131 if (mask & GL_COLOR_BUFFER_BIT)
2132 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002133 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002134 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002135
He Yunchao66a41a22016-12-15 16:45:05 +08002136 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002137 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002138 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002139
Geoff Langa15472a2015-08-11 11:48:03 -04002140 for (size_t drawbufferIdx = 0;
2141 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002142 {
Geoff Langa15472a2015-08-11 11:48:03 -04002143 const FramebufferAttachment *attachment =
2144 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2145 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002146 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002147 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002148
Geoff Langb2f3d052013-08-13 12:49:27 -04002149 // The GL ES 3.0.2 spec (pg 193) states that:
2150 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002151 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2152 // as well
2153 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2154 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002155 // Changes with EXT_color_buffer_float:
2156 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002157 GLenum readComponentType = readFormat.info->componentType;
2158 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002159 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002160 readComponentType == GL_SIGNED_NORMALIZED);
2161 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2162 drawComponentType == GL_SIGNED_NORMALIZED);
2163
2164 if (extensions.colorBufferFloat)
2165 {
2166 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2167 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2168
2169 if (readFixedOrFloat != drawFixedOrFloat)
2170 {
Jamie Madill437fa652016-05-03 15:13:24 -04002171 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002172 "If the read buffer contains fixed-point or "
2173 "floating-point values, the draw buffer "
2174 "must as well."));
2175 return false;
2176 }
2177 }
2178 else if (readFixedPoint != drawFixedPoint)
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 "
2182 "values, the draw buffer must as well."));
2183 return false;
2184 }
2185
2186 if (readComponentType == GL_UNSIGNED_INT &&
2187 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002188 {
Jamie Madill437fa652016-05-03 15:13:24 -04002189 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002190 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002191 }
2192
Jamie Madill6163c752015-12-07 16:32:59 -05002193 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002194 {
Jamie Madill437fa652016-05-03 15:13:24 -04002195 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002196 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002197 }
2198
Jamie Madilla3944d42016-07-22 22:13:26 -04002199 if (readColorBuffer->getSamples() > 0 &&
2200 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002201 {
Jamie Madill437fa652016-05-03 15:13:24 -04002202 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002203 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002204 }
2205 }
2206 }
2207
Jamie Madilla3944d42016-07-22 22:13:26 -04002208 if ((readFormat.info->componentType == GL_INT ||
2209 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2210 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002211 {
Jamie Madill437fa652016-05-03 15:13:24 -04002212 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002213 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002214 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002215 }
He Yunchao66a41a22016-12-15 16:45:05 +08002216 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2217 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2218 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2219 // situation is an application error that would lead to a crash in ANGLE.
2220 else if (drawFramebuffer->hasEnabledDrawBuffer())
2221 {
2222 context->handleError(Error(
2223 GL_INVALID_OPERATION,
2224 "Attempt to read from a missing color attachment of a complete framebuffer."));
2225 return false;
2226 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002227 }
2228
He Yunchaoced53ae2016-11-29 15:00:51 +08002229 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002230 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2231 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002232 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002233 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002234 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002235 const gl::FramebufferAttachment *readBuffer =
2236 readFramebuffer->getAttachment(attachments[i]);
2237 const gl::FramebufferAttachment *drawBuffer =
2238 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002239
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002240 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002241 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002242 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002243 {
Jamie Madill437fa652016-05-03 15:13:24 -04002244 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002245 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002246 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002247
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002248 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002249 {
Jamie Madill437fa652016-05-03 15:13:24 -04002250 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002251 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002252 }
2253 }
He Yunchao66a41a22016-12-15 16:45:05 +08002254 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2255 else if (drawBuffer)
2256 {
2257 context->handleError(Error(GL_INVALID_OPERATION,
2258 "Attempt to read from a missing depth/stencil "
2259 "attachment of a complete framebuffer."));
2260 return false;
2261 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002262 }
2263 }
2264
2265 return true;
2266}
2267
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002268bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002269 GLint x,
2270 GLint y,
2271 GLsizei width,
2272 GLsizei height,
2273 GLenum format,
2274 GLenum type,
2275 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002276{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002277 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2278}
2279
2280bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2281 GLint x,
2282 GLint y,
2283 GLsizei width,
2284 GLsizei height,
2285 GLenum format,
2286 GLenum type,
2287 GLsizei bufSize,
2288 GLsizei *length,
2289 GLvoid *pixels)
2290{
2291 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002292 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002293 return false;
2294 }
2295
Geoff Lang62fce5b2016-09-30 10:46:35 -04002296 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2297 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002298 {
Geoff Langb1196682014-07-23 13:47:29 -04002299 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002300 }
2301
Geoff Lang62fce5b2016-09-30 10:46:35 -04002302 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002303 {
Geoff Langb1196682014-07-23 13:47:29 -04002304 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002305 }
2306
Jamie Madillc29968b2016-01-20 11:17:23 -05002307 return true;
2308}
2309
2310bool ValidateReadnPixelsEXT(Context *context,
2311 GLint x,
2312 GLint y,
2313 GLsizei width,
2314 GLsizei height,
2315 GLenum format,
2316 GLenum type,
2317 GLsizei bufSize,
2318 GLvoid *pixels)
2319{
2320 if (bufSize < 0)
2321 {
Jamie Madill437fa652016-05-03 15:13:24 -04002322 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002323 return false;
2324 }
2325
Geoff Lang62fce5b2016-09-30 10:46:35 -04002326 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2327 pixels);
2328}
Jamie Madill26e91952014-03-05 15:01:27 -05002329
Geoff Lang62fce5b2016-09-30 10:46:35 -04002330bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2331 GLint x,
2332 GLint y,
2333 GLsizei width,
2334 GLsizei height,
2335 GLenum format,
2336 GLenum type,
2337 GLsizei bufSize,
2338 GLsizei *length,
2339 GLvoid *data)
2340{
2341 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002342 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002343 return false;
2344 }
2345
Geoff Lang62fce5b2016-09-30 10:46:35 -04002346 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002347 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002348 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002349 }
2350
Geoff Lang62fce5b2016-09-30 10:46:35 -04002351 if (!ValidateRobustBufferSize(context, bufSize, *length))
2352 {
2353 return false;
2354 }
2355
2356 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002357}
2358
Olli Etuaho41997e72016-03-10 13:38:39 +02002359bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002360{
2361 if (!context->getExtensions().occlusionQueryBoolean &&
2362 !context->getExtensions().disjointTimerQuery)
2363 {
Jamie Madill437fa652016-05-03 15:13:24 -04002364 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002365 return false;
2366 }
2367
Olli Etuaho41997e72016-03-10 13:38:39 +02002368 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002369}
2370
Olli Etuaho41997e72016-03-10 13:38:39 +02002371bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002372{
2373 if (!context->getExtensions().occlusionQueryBoolean &&
2374 !context->getExtensions().disjointTimerQuery)
2375 {
Jamie Madill437fa652016-05-03 15:13:24 -04002376 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002377 return false;
2378 }
2379
Olli Etuaho41997e72016-03-10 13:38:39 +02002380 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002381}
2382
2383bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002384{
2385 if (!ValidQueryType(context, target))
2386 {
Jamie Madill437fa652016-05-03 15:13:24 -04002387 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002388 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002389 }
2390
2391 if (id == 0)
2392 {
Jamie Madill437fa652016-05-03 15:13:24 -04002393 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002394 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002395 }
2396
2397 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2398 // of zero, if the active query object name for <target> is non-zero (for the
2399 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2400 // the active query for either target is non-zero), if <id> is the name of an
2401 // existing query object whose type does not match <target>, or if <id> is the
2402 // active query object name for any query type, the error INVALID_OPERATION is
2403 // generated.
2404
2405 // Ensure no other queries are active
2406 // NOTE: If other queries than occlusion are supported, we will need to check
2407 // separately that:
2408 // a) The query ID passed is not the current active query for any target/type
2409 // b) There are no active queries for the requested target (and in the case
2410 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2411 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002412
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002413 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002414 {
Jamie Madill437fa652016-05-03 15:13:24 -04002415 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002416 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002417 }
2418
2419 Query *queryObject = context->getQuery(id, true, target);
2420
2421 // check that name was obtained with glGenQueries
2422 if (!queryObject)
2423 {
Jamie Madill437fa652016-05-03 15:13:24 -04002424 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002425 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002426 }
2427
2428 // check for type mismatch
2429 if (queryObject->getType() != target)
2430 {
Jamie Madill437fa652016-05-03 15:13:24 -04002431 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002432 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002433 }
2434
2435 return true;
2436}
2437
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002438bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2439{
2440 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002441 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002442 {
Jamie Madill437fa652016-05-03 15:13:24 -04002443 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002444 return false;
2445 }
2446
2447 return ValidateBeginQueryBase(context, target, id);
2448}
2449
2450bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002451{
2452 if (!ValidQueryType(context, target))
2453 {
Jamie Madill437fa652016-05-03 15:13:24 -04002454 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002455 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002456 }
2457
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002458 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002459
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002460 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002461 {
Jamie Madill437fa652016-05-03 15:13:24 -04002462 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002463 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002464 }
2465
Jamie Madill45c785d2014-05-13 14:09:34 -04002466 return true;
2467}
2468
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002469bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2470{
2471 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002472 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002473 {
Jamie Madill437fa652016-05-03 15:13:24 -04002474 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002475 return false;
2476 }
2477
2478 return ValidateEndQueryBase(context, target);
2479}
2480
2481bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2482{
2483 if (!context->getExtensions().disjointTimerQuery)
2484 {
Jamie Madill437fa652016-05-03 15:13:24 -04002485 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002486 return false;
2487 }
2488
2489 if (target != GL_TIMESTAMP_EXT)
2490 {
Jamie Madill437fa652016-05-03 15:13:24 -04002491 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002492 return false;
2493 }
2494
2495 Query *queryObject = context->getQuery(id, true, target);
2496 if (queryObject == nullptr)
2497 {
Jamie Madill437fa652016-05-03 15:13:24 -04002498 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002499 return false;
2500 }
2501
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002502 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002503 {
Jamie Madill437fa652016-05-03 15:13:24 -04002504 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002505 return false;
2506 }
2507
2508 return true;
2509}
2510
Geoff Lang2186c382016-10-14 10:54:54 -04002511bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002512{
Geoff Lang2186c382016-10-14 10:54:54 -04002513 if (numParams)
2514 {
2515 *numParams = 0;
2516 }
2517
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002518 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2519 {
Jamie Madill437fa652016-05-03 15:13:24 -04002520 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002521 return false;
2522 }
2523
2524 switch (pname)
2525 {
2526 case GL_CURRENT_QUERY_EXT:
2527 if (target == GL_TIMESTAMP_EXT)
2528 {
Jamie Madill437fa652016-05-03 15:13:24 -04002529 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002530 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2531 return false;
2532 }
2533 break;
2534 case GL_QUERY_COUNTER_BITS_EXT:
2535 if (!context->getExtensions().disjointTimerQuery ||
2536 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2537 {
Jamie Madill437fa652016-05-03 15:13:24 -04002538 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002539 return false;
2540 }
2541 break;
2542 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002543 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002544 return false;
2545 }
2546
Geoff Lang2186c382016-10-14 10:54:54 -04002547 if (numParams)
2548 {
2549 // All queries return only one value
2550 *numParams = 1;
2551 }
2552
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002553 return true;
2554}
2555
2556bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2557{
2558 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002559 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002560 {
Jamie Madill437fa652016-05-03 15:13:24 -04002561 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002562 return false;
2563 }
2564
Geoff Lang2186c382016-10-14 10:54:54 -04002565 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002566}
2567
Geoff Lang2186c382016-10-14 10:54:54 -04002568bool ValidateGetQueryivRobustANGLE(Context *context,
2569 GLenum target,
2570 GLenum pname,
2571 GLsizei bufSize,
2572 GLsizei *length,
2573 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002574{
Geoff Lang2186c382016-10-14 10:54:54 -04002575 if (!ValidateRobustEntryPoint(context, bufSize))
2576 {
2577 return false;
2578 }
2579
2580 if (!ValidateGetQueryivBase(context, target, pname, length))
2581 {
2582 return false;
2583 }
2584
2585 if (!ValidateRobustBufferSize(context, bufSize, *length))
2586 {
2587 return false;
2588 }
2589
2590 return true;
2591}
2592
2593bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2594{
2595 if (numParams)
2596 {
2597 *numParams = 0;
2598 }
2599
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002600 Query *queryObject = context->getQuery(id, false, GL_NONE);
2601
2602 if (!queryObject)
2603 {
Jamie Madill437fa652016-05-03 15:13:24 -04002604 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002605 return false;
2606 }
2607
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002608 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002609 {
Jamie Madill437fa652016-05-03 15:13:24 -04002610 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002611 return false;
2612 }
2613
2614 switch (pname)
2615 {
2616 case GL_QUERY_RESULT_EXT:
2617 case GL_QUERY_RESULT_AVAILABLE_EXT:
2618 break;
2619
2620 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002621 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002622 return false;
2623 }
2624
Geoff Lang2186c382016-10-14 10:54:54 -04002625 if (numParams)
2626 {
2627 *numParams = 1;
2628 }
2629
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002630 return true;
2631}
2632
2633bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2634{
2635 if (!context->getExtensions().disjointTimerQuery)
2636 {
Jamie Madill437fa652016-05-03 15:13:24 -04002637 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002638 return false;
2639 }
Geoff Lang2186c382016-10-14 10:54:54 -04002640 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2641}
2642
2643bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2644 GLuint id,
2645 GLenum pname,
2646 GLsizei bufSize,
2647 GLsizei *length,
2648 GLint *params)
2649{
2650 if (!context->getExtensions().disjointTimerQuery)
2651 {
2652 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2653 return false;
2654 }
2655
2656 if (!ValidateRobustEntryPoint(context, bufSize))
2657 {
2658 return false;
2659 }
2660
2661 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2662 {
2663 return false;
2664 }
2665
2666 if (!ValidateRobustBufferSize(context, bufSize, *length))
2667 {
2668 return false;
2669 }
2670
2671 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002672}
2673
2674bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2675{
2676 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002677 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002678 {
Jamie Madill437fa652016-05-03 15:13:24 -04002679 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002680 return false;
2681 }
Geoff Lang2186c382016-10-14 10:54:54 -04002682 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2683}
2684
2685bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2686 GLuint id,
2687 GLenum pname,
2688 GLsizei bufSize,
2689 GLsizei *length,
2690 GLuint *params)
2691{
2692 if (!context->getExtensions().disjointTimerQuery &&
2693 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2694 {
2695 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2696 return false;
2697 }
2698
2699 if (!ValidateRobustEntryPoint(context, bufSize))
2700 {
2701 return false;
2702 }
2703
2704 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2705 {
2706 return false;
2707 }
2708
2709 if (!ValidateRobustBufferSize(context, bufSize, *length))
2710 {
2711 return false;
2712 }
2713
2714 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002715}
2716
2717bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2718{
2719 if (!context->getExtensions().disjointTimerQuery)
2720 {
Jamie Madill437fa652016-05-03 15:13:24 -04002721 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002722 return false;
2723 }
Geoff Lang2186c382016-10-14 10:54:54 -04002724 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2725}
2726
2727bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2728 GLuint id,
2729 GLenum pname,
2730 GLsizei bufSize,
2731 GLsizei *length,
2732 GLint64 *params)
2733{
2734 if (!context->getExtensions().disjointTimerQuery)
2735 {
2736 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2737 return false;
2738 }
2739
2740 if (!ValidateRobustEntryPoint(context, bufSize))
2741 {
2742 return false;
2743 }
2744
2745 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2746 {
2747 return false;
2748 }
2749
2750 if (!ValidateRobustBufferSize(context, bufSize, *length))
2751 {
2752 return false;
2753 }
2754
2755 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002756}
2757
2758bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2759{
2760 if (!context->getExtensions().disjointTimerQuery)
2761 {
Jamie Madill437fa652016-05-03 15:13:24 -04002762 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002763 return false;
2764 }
Geoff Lang2186c382016-10-14 10:54:54 -04002765 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2766}
2767
2768bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2769 GLuint id,
2770 GLenum pname,
2771 GLsizei bufSize,
2772 GLsizei *length,
2773 GLuint64 *params)
2774{
2775 if (!context->getExtensions().disjointTimerQuery)
2776 {
2777 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2778 return false;
2779 }
2780
2781 if (!ValidateRobustEntryPoint(context, bufSize))
2782 {
2783 return false;
2784 }
2785
2786 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2787 {
2788 return false;
2789 }
2790
2791 if (!ValidateRobustBufferSize(context, bufSize, *length))
2792 {
2793 return false;
2794 }
2795
2796 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002797}
2798
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002799bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002800 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002801 GLuint program,
2802 GLint location,
2803 GLsizei count)
2804{
2805 // Check for ES31 program uniform entry points
2806 if (context->getClientVersion() < Version(3, 1))
2807 {
2808 context->handleError(Error(GL_INVALID_OPERATION));
2809 return false;
2810 }
2811
2812 const LinkedUniform *uniform = nullptr;
2813 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002814 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2815 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002816}
2817
Frank Henigmana98a6472017-02-02 21:38:32 -05002818bool ValidateProgramUniform1iv(gl::Context *context,
2819 GLuint program,
2820 GLint location,
2821 GLsizei count,
2822 const GLint *value)
2823{
2824 // Check for ES31 program uniform entry points
2825 if (context->getClientVersion() < Version(3, 1))
2826 {
2827 context->handleError(Error(GL_INVALID_OPERATION));
2828 return false;
2829 }
2830
2831 const LinkedUniform *uniform = nullptr;
2832 gl::Program *programObject = GetValidProgram(context, program);
2833 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2834 ValidateUniform1ivValue(context, uniform->type, count, value);
2835}
2836
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002837bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002838 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002839 GLuint program,
2840 GLint location,
2841 GLsizei count,
2842 GLboolean transpose)
2843{
2844 // Check for ES31 program uniform entry points
2845 if (context->getClientVersion() < Version(3, 1))
2846 {
2847 context->handleError(Error(GL_INVALID_OPERATION));
2848 return false;
2849 }
2850
2851 const LinkedUniform *uniform = nullptr;
2852 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002853 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2854 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002855}
2856
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002857bool ValidateUniform(gl::Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002858{
2859 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002860 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002861 {
Jamie Madill437fa652016-05-03 15:13:24 -04002862 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002863 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002864 }
2865
Jamie Madill62d31cb2015-09-11 13:25:51 -04002866 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002867 gl::Program *programObject = context->getGLState().getProgram();
2868 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2869 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002870}
2871
Frank Henigmana98a6472017-02-02 21:38:32 -05002872bool ValidateUniform1iv(gl::Context *context, GLint location, GLsizei count, const GLint *value)
2873{
2874 const LinkedUniform *uniform = nullptr;
2875 gl::Program *programObject = context->getGLState().getProgram();
2876 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2877 ValidateUniform1ivValue(context, uniform->type, count, value);
2878}
2879
He Yunchaoced53ae2016-11-29 15:00:51 +08002880bool ValidateUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002881 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002882 GLint location,
2883 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002884 GLboolean transpose)
2885{
2886 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002887 int rows = VariableRowCount(valueType);
2888 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002889 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002890 {
Jamie Madill437fa652016-05-03 15:13:24 -04002891 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002892 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002893 }
2894
Martin Radev1be913c2016-07-11 17:59:16 +03002895 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002896 {
Jamie Madill437fa652016-05-03 15:13:24 -04002897 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002898 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002899 }
2900
Jamie Madill62d31cb2015-09-11 13:25:51 -04002901 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002902 gl::Program *programObject = context->getGLState().getProgram();
2903 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2904 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002905}
2906
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002907bool ValidateStateQuery(ValidationContext *context,
2908 GLenum pname,
2909 GLenum *nativeType,
2910 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002911{
2912 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2913 {
Jamie Madill437fa652016-05-03 15:13:24 -04002914 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002915 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002916 }
2917
Jamie Madill0af26e12015-03-05 19:54:33 -05002918 const Caps &caps = context->getCaps();
2919
Jamie Madill893ab082014-05-16 16:56:10 -04002920 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2921 {
2922 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2923
Jamie Madill0af26e12015-03-05 19:54:33 -05002924 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002925 {
Jamie Madill437fa652016-05-03 15:13:24 -04002926 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002927 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002928 }
2929 }
2930
2931 switch (pname)
2932 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002933 case GL_TEXTURE_BINDING_2D:
2934 case GL_TEXTURE_BINDING_CUBE_MAP:
2935 case GL_TEXTURE_BINDING_3D:
2936 case GL_TEXTURE_BINDING_2D_ARRAY:
2937 break;
2938 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2939 if (!context->getExtensions().eglStreamConsumerExternal &&
2940 !context->getExtensions().eglImageExternal)
2941 {
2942 context->handleError(Error(GL_INVALID_ENUM,
2943 "Neither NV_EGL_stream_consumer_external nor "
2944 "GL_OES_EGL_image_external extensions enabled"));
2945 return false;
2946 }
2947 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002948
He Yunchaoced53ae2016-11-29 15:00:51 +08002949 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2950 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002951 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002952 if (context->getGLState().getReadFramebuffer()->checkStatus(
2953 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002954 {
Jamie Madill437fa652016-05-03 15:13:24 -04002955 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002956 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002957 }
2958
Jamie Madill51f40ec2016-06-15 14:06:00 -04002959 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2960 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002961
2962 if (framebuffer->getReadBufferState() == GL_NONE)
2963 {
2964 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2965 return false;
2966 }
2967
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002968 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002969 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002970 {
Jamie Madill437fa652016-05-03 15:13:24 -04002971 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002972 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002973 }
2974 }
2975 break;
2976
He Yunchaoced53ae2016-11-29 15:00:51 +08002977 default:
2978 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002979 }
2980
2981 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002982 if (*numParams == 0)
2983 {
2984 return false;
2985 }
2986
2987 return true;
2988}
2989
2990bool ValidateRobustStateQuery(ValidationContext *context,
2991 GLenum pname,
2992 GLsizei bufSize,
2993 GLenum *nativeType,
2994 unsigned int *numParams)
2995{
2996 if (!ValidateRobustEntryPoint(context, bufSize))
2997 {
2998 return false;
2999 }
3000
3001 if (!ValidateStateQuery(context, pname, nativeType, numParams))
3002 {
3003 return false;
3004 }
3005
3006 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04003007 {
3008 return false;
3009 }
3010
3011 return true;
3012}
3013
Jamie Madillc29968b2016-01-20 11:17:23 -05003014bool ValidateCopyTexImageParametersBase(ValidationContext *context,
3015 GLenum target,
3016 GLint level,
3017 GLenum internalformat,
3018 bool isSubImage,
3019 GLint xoffset,
3020 GLint yoffset,
3021 GLint zoffset,
3022 GLint x,
3023 GLint y,
3024 GLsizei width,
3025 GLsizei height,
3026 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04003027 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04003028{
Jamie Madill560a8d82014-05-21 13:06:20 -04003029 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
3030 {
Jamie Madill437fa652016-05-03 15:13:24 -04003031 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003032 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003033 }
3034
He Yunchaoced53ae2016-11-29 15:00:51 +08003035 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3036 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04003037 {
Jamie Madill437fa652016-05-03 15:13:24 -04003038 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003039 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003040 }
3041
3042 if (border != 0)
3043 {
Jamie Madill437fa652016-05-03 15:13:24 -04003044 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003045 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003046 }
3047
3048 if (!ValidMipLevel(context, target, level))
3049 {
Jamie Madill437fa652016-05-03 15:13:24 -04003050 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003051 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003052 }
3053
Jamie Madill51f40ec2016-06-15 14:06:00 -04003054 const auto &state = context->getGLState();
3055 auto readFramebuffer = state.getReadFramebuffer();
3056 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003057 {
Jamie Madill437fa652016-05-03 15:13:24 -04003058 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003059 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003060 }
3061
Jamie Madill51f40ec2016-06-15 14:06:00 -04003062 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003063 {
Jamie Madill437fa652016-05-03 15:13:24 -04003064 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003065 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003066 }
3067
Martin Radev138064f2016-07-15 12:03:41 +03003068 if (readFramebuffer->getReadBufferState() == GL_NONE)
3069 {
3070 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3071 return false;
3072 }
3073
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003074 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3075 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003076 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003077 // situation is an application error that would lead to a crash in ANGLE.
3078 if (readFramebuffer->getReadColorbuffer() == nullptr)
3079 {
3080 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3081 return false;
3082 }
3083
Geoff Langaae65a42014-05-26 12:43:44 -04003084 const gl::Caps &caps = context->getCaps();
3085
Geoff Langaae65a42014-05-26 12:43:44 -04003086 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003087 switch (target)
3088 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003089 case GL_TEXTURE_2D:
3090 maxDimension = caps.max2DTextureSize;
3091 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003092
He Yunchaoced53ae2016-11-29 15:00:51 +08003093 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3094 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3095 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3096 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3097 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3098 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3099 maxDimension = caps.maxCubeMapTextureSize;
3100 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003101
He Yunchaoced53ae2016-11-29 15:00:51 +08003102 case GL_TEXTURE_2D_ARRAY:
3103 maxDimension = caps.max2DTextureSize;
3104 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003105
He Yunchaoced53ae2016-11-29 15:00:51 +08003106 case GL_TEXTURE_3D:
3107 maxDimension = caps.max3DTextureSize;
3108 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003109
He Yunchaoced53ae2016-11-29 15:00:51 +08003110 default:
3111 context->handleError(Error(GL_INVALID_ENUM));
3112 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003113 }
3114
Jamie Madillc29968b2016-01-20 11:17:23 -05003115 gl::Texture *texture =
3116 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003117 if (!texture)
3118 {
Jamie Madill437fa652016-05-03 15:13:24 -04003119 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003120 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003121 }
3122
Geoff Lang69cce582015-09-17 13:20:36 -04003123 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003124 {
Jamie Madill437fa652016-05-03 15:13:24 -04003125 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003126 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003127 }
3128
Geoff Lang5d601382014-07-22 15:14:06 -04003129 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3130
3131 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003132 {
Jamie Madill437fa652016-05-03 15:13:24 -04003133 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003134 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003135 }
3136
Geoff Langa9be0dc2014-12-17 12:34:40 -05003137 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003138 {
Jamie Madill437fa652016-05-03 15:13:24 -04003139 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003140 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003141 }
3142
3143 if (isSubImage)
3144 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003145 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3146 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3147 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003148 {
Jamie Madill437fa652016-05-03 15:13:24 -04003149 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003150 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003151 }
3152 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003153 else
3154 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003155 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003156 {
Jamie Madill437fa652016-05-03 15:13:24 -04003157 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003158 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003159 }
3160
Geoff Langeb66a6e2016-10-31 13:06:12 -04003161 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003162 {
Jamie Madill437fa652016-05-03 15:13:24 -04003163 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003164 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003165 }
3166
3167 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003168 if (static_cast<int>(width) > maxLevelDimension ||
3169 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003170 {
Jamie Madill437fa652016-05-03 15:13:24 -04003171 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003172 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003173 }
3174 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003175
Jamie Madill0c8abca2016-07-22 20:21:26 -04003176 if (textureFormatOut)
3177 {
3178 *textureFormatOut = texture->getFormat(target, level);
3179 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003180
3181 // Detect texture copying feedback loops for WebGL.
3182 if (context->getExtensions().webglCompatibility)
3183 {
3184 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level))
3185 {
3186 context->handleError(Error(GL_INVALID_OPERATION,
3187 "Texture copying feedback loop formed between Framebuffer "
3188 "and specified Texture level."));
3189 return false;
3190 }
3191 }
3192
Jamie Madill560a8d82014-05-21 13:06:20 -04003193 return true;
3194}
3195
Jiajia Qind9671222016-11-29 16:30:31 +08003196bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003197{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003198 switch (mode)
3199 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003200 case GL_POINTS:
3201 case GL_LINES:
3202 case GL_LINE_LOOP:
3203 case GL_LINE_STRIP:
3204 case GL_TRIANGLES:
3205 case GL_TRIANGLE_STRIP:
3206 case GL_TRIANGLE_FAN:
3207 break;
3208 default:
3209 context->handleError(Error(GL_INVALID_ENUM));
3210 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003211 }
3212
Jamie Madill250d33f2014-06-06 17:09:03 -04003213 if (count < 0)
3214 {
Jamie Madill437fa652016-05-03 15:13:24 -04003215 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003216 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003217 }
3218
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003219 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003220
Jamie Madill250d33f2014-06-06 17:09:03 -04003221 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003222 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003223 {
Jamie Madill437fa652016-05-03 15:13:24 -04003224 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003225 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003226 }
3227
Jamie Madillcbcde722017-01-06 14:50:00 -05003228 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3229 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003230 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003231 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3232 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003233 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003234 const FramebufferAttachment *dsAttachment =
3235 framebuffer->getStencilOrDepthStencilAttachment();
3236 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003237 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003238 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003239
3240 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3241 bool differentWritemasks =
3242 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3243 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3244 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3245 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3246
3247 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003248 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003249 if (!context->getExtensions().webglCompatibility)
3250 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003251 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3252 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003253 }
Jamie Madill437fa652016-05-03 15:13:24 -04003254 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003255 return false;
3256 }
Jamie Madillac528012014-06-20 13:21:23 -04003257 }
3258
Jamie Madill51f40ec2016-06-15 14:06:00 -04003259 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003260 {
Jamie Madill437fa652016-05-03 15:13:24 -04003261 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003262 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003263 }
3264
Geoff Lang7dd2e102014-11-10 15:19:26 -05003265 gl::Program *program = state.getProgram();
3266 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003267 {
Jamie Madill437fa652016-05-03 15:13:24 -04003268 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003269 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003270 }
3271
Geoff Lang7dd2e102014-11-10 15:19:26 -05003272 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003273 {
Jamie Madill437fa652016-05-03 15:13:24 -04003274 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003275 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003276 }
3277
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003278 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003279 for (unsigned int uniformBlockIndex = 0;
3280 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003281 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003282 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003283 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003284 const OffsetBindingPointer<Buffer> &uniformBuffer =
3285 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003286
Geoff Lang5d124a62015-09-15 13:03:27 -04003287 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003288 {
3289 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003290 context->handleError(
3291 Error(GL_INVALID_OPERATION,
3292 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003293 return false;
3294 }
3295
Geoff Lang5d124a62015-09-15 13:03:27 -04003296 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003297 if (uniformBufferSize == 0)
3298 {
3299 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003300 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003301 }
3302
Jamie Madill62d31cb2015-09-11 13:25:51 -04003303 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003304 {
3305 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003306 context->handleError(
3307 Error(GL_INVALID_OPERATION,
3308 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003309 return false;
3310 }
3311 }
3312
Jamie Madilla4595b82017-01-11 17:36:34 -05003313 // Detect rendering feedback loops for WebGL.
3314 if (context->getExtensions().webglCompatibility)
3315 {
3316 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3317 {
3318 context->handleError(
3319 Error(GL_INVALID_OPERATION,
3320 "Rendering feedback loop formed between Framebuffer and active Texture."));
3321 return false;
3322 }
3323 }
3324
Jamie Madill250d33f2014-06-06 17:09:03 -04003325 // No-op if zero count
3326 return (count > 0);
3327}
3328
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003329bool ValidateDrawArrays(ValidationContext *context,
3330 GLenum mode,
3331 GLint first,
3332 GLsizei count,
3333 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003334{
Jamie Madillfd716582014-06-06 17:09:04 -04003335 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003336 {
Jamie Madill437fa652016-05-03 15:13:24 -04003337 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003338 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003339 }
3340
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003341 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003342 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003343 if (curTransformFeedback && curTransformFeedback->isActive() &&
3344 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003345 {
3346 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003347 // that does not match the current transform feedback object's draw mode (if transform
3348 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003349 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003350 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003351 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003352 }
3353
Jiajia Qind9671222016-11-29 16:30:31 +08003354 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003355 {
3356 return false;
3357 }
3358
Corentin Wallez71168a02016-12-19 15:11:18 -08003359 // Check the computation of maxVertex doesn't overflow.
3360 // - first < 0 or count < 0 have been checked as an error condition
3361 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3362 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3363 ASSERT(count > 0 && first >= 0);
3364 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3365 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003366 {
3367 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3368 return false;
3369 }
3370
Corentin Wallez71168a02016-12-19 15:11:18 -08003371 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003372 {
3373 return false;
3374 }
3375
3376 return true;
3377}
3378
He Yunchaoced53ae2016-11-29 15:00:51 +08003379bool ValidateDrawArraysInstanced(Context *context,
3380 GLenum mode,
3381 GLint first,
3382 GLsizei count,
3383 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003384{
3385 if (primcount < 0)
3386 {
Jamie Madill437fa652016-05-03 15:13:24 -04003387 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003388 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003389 }
3390
Jamie Madill2b976812014-08-25 15:47:49 -04003391 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003392 {
3393 return false;
3394 }
3395
3396 // No-op if zero primitive count
3397 return (primcount > 0);
3398}
3399
Geoff Lang87a93302014-09-16 13:29:43 -04003400static bool ValidateDrawInstancedANGLE(Context *context)
3401{
3402 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003403 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003404
Geoff Lang7dd2e102014-11-10 15:19:26 -05003405 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003406
3407 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003408 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003409 {
3410 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003411 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003412 {
3413 return true;
3414 }
3415 }
3416
Jamie Madill437fa652016-05-03 15:13:24 -04003417 context->handleError(Error(GL_INVALID_OPERATION,
3418 "ANGLE_instanced_arrays requires that at least one active attribute"
3419 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003420 return false;
3421}
3422
He Yunchaoced53ae2016-11-29 15:00:51 +08003423bool ValidateDrawArraysInstancedANGLE(Context *context,
3424 GLenum mode,
3425 GLint first,
3426 GLsizei count,
3427 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003428{
3429 if (!ValidateDrawInstancedANGLE(context))
3430 {
3431 return false;
3432 }
3433
3434 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3435}
3436
Jiajia Qind9671222016-11-29 16:30:31 +08003437bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003438{
Jamie Madill250d33f2014-06-06 17:09:03 -04003439 switch (type)
3440 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003441 case GL_UNSIGNED_BYTE:
3442 case GL_UNSIGNED_SHORT:
3443 break;
3444 case GL_UNSIGNED_INT:
3445 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3446 {
3447 context->handleError(Error(GL_INVALID_ENUM));
3448 return false;
3449 }
3450 break;
3451 default:
3452 context->handleError(Error(GL_INVALID_ENUM));
3453 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003454 }
3455
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003456 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003457
3458 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003459 if (curTransformFeedback && curTransformFeedback->isActive() &&
3460 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003461 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003462 // It is an invalid operation to call DrawElements, DrawRangeElements or
3463 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003464 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003465 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003466 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003467 }
3468
Jiajia Qind9671222016-11-29 16:30:31 +08003469 return true;
3470}
3471
3472bool ValidateDrawElements(ValidationContext *context,
3473 GLenum mode,
3474 GLsizei count,
3475 GLenum type,
3476 const GLvoid *indices,
3477 GLsizei primcount,
3478 IndexRange *indexRangeOut)
3479{
3480 if (!ValidateDrawElementsBase(context, type))
3481 return false;
3482
3483 const State &state = context->getGLState();
3484
Jamie Madill250d33f2014-06-06 17:09:03 -04003485 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003486 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003487 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003488 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04003489 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003490 }
3491
He Yunchaoced53ae2016-11-29 15:00:51 +08003492 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003493 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003494
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003495 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3496
3497 if (context->getExtensions().webglCompatibility)
3498 {
3499 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3500 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3501 {
3502 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3503 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3504 // data type passed to the call, or an INVALID_OPERATION error is generated.
3505 context->handleError(Error(GL_INVALID_OPERATION,
3506 "indices must be a multiple of the element type size."));
3507 return false;
3508 }
3509 if (!elementArrayBuffer && count > 0)
3510 {
3511 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3512 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3513 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3514 context->handleError(Error(GL_INVALID_OPERATION,
3515 "There is no element array buffer bound and count > 0."));
3516 return false;
3517 }
3518 }
3519
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003520 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003521 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003522 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003523 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003524 GLint64 offset = reinterpret_cast<GLint64>(indices);
3525 GLint64 byteCount =
3526 static_cast<GLint64>(typeBytes) * static_cast<GLint64>(count) + offset;
3527
3528 // check for integer overflows
3529 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeBytes) ||
3530 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3531 {
3532 context->handleError(Error(GL_OUT_OF_MEMORY, "Integer overflow."));
3533 return false;
3534 }
3535
3536 // Check for reading past the end of the bound buffer object
3537 if (byteCount > elementArrayBuffer->getSize())
3538 {
3539 context->handleError(
3540 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
3541 return false;
3542 }
3543 }
3544 else if (!indices)
3545 {
3546 // This is an application error that would normally result in a crash,
3547 // but we catch it and return an error
3548 context->handleError(
3549 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003550 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003551 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003552 }
3553
Jiajia Qind9671222016-11-29 16:30:31 +08003554 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003555 {
3556 return false;
3557 }
3558
Jamie Madill2b976812014-08-25 15:47:49 -04003559 // Use max index to validate if our vertex buffers are large enough for the pull.
3560 // TODO: offer fast path, with disabled index validation.
3561 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3562 if (elementArrayBuffer)
3563 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003564 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003565 Error error =
3566 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3567 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003568 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003569 {
Jamie Madill437fa652016-05-03 15:13:24 -04003570 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003571 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003572 }
3573 }
3574 else
3575 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003576 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003577 }
3578
Jamie Madille79b1e12015-11-04 16:36:37 -05003579 // If we use an index greater than our maximum supported index range, return an error.
3580 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3581 // return an error if possible here.
3582 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3583 {
Jamie Madill437fa652016-05-03 15:13:24 -04003584 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003585 return false;
3586 }
3587
Corentin Wallez92db6942016-12-09 13:10:36 -05003588 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3589 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003590 {
3591 return false;
3592 }
3593
Geoff Lang3edfe032015-09-04 16:38:24 -04003594 // No op if there are no real indices in the index data (all are primitive restart).
3595 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003596}
3597
Geoff Langb1196682014-07-23 13:47:29 -04003598bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003599 GLenum mode,
3600 GLsizei count,
3601 GLenum type,
3602 const GLvoid *indices,
3603 GLsizei primcount,
3604 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003605{
3606 if (primcount < 0)
3607 {
Jamie Madill437fa652016-05-03 15:13:24 -04003608 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003609 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003610 }
3611
Jamie Madill2b976812014-08-25 15:47:49 -04003612 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003613 {
3614 return false;
3615 }
3616
3617 // No-op zero primitive count
3618 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003619}
3620
Geoff Lang3edfe032015-09-04 16:38:24 -04003621bool ValidateDrawElementsInstancedANGLE(Context *context,
3622 GLenum mode,
3623 GLsizei count,
3624 GLenum type,
3625 const GLvoid *indices,
3626 GLsizei primcount,
3627 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003628{
3629 if (!ValidateDrawInstancedANGLE(context))
3630 {
3631 return false;
3632 }
3633
He Yunchaoced53ae2016-11-29 15:00:51 +08003634 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3635 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003636}
3637
He Yunchaoced53ae2016-11-29 15:00:51 +08003638bool ValidateFramebufferTextureBase(Context *context,
3639 GLenum target,
3640 GLenum attachment,
3641 GLuint texture,
3642 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003643{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003644 if (!ValidFramebufferTarget(target))
3645 {
Jamie Madill437fa652016-05-03 15:13:24 -04003646 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003647 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003648 }
3649
3650 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003651 {
3652 return false;
3653 }
3654
Jamie Madill55ec3b12014-07-03 10:38:57 -04003655 if (texture != 0)
3656 {
3657 gl::Texture *tex = context->getTexture(texture);
3658
3659 if (tex == NULL)
3660 {
Jamie Madill437fa652016-05-03 15:13:24 -04003661 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003662 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003663 }
3664
3665 if (level < 0)
3666 {
Jamie Madill437fa652016-05-03 15:13:24 -04003667 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003668 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003669 }
3670 }
3671
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003672 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003673 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003674
Jamie Madill84115c92015-04-23 15:00:07 -04003675 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003676 {
Jamie Madill437fa652016-05-03 15:13:24 -04003677 context->handleError(
3678 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003679 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003680 }
3681
3682 return true;
3683}
3684
He Yunchaoced53ae2016-11-29 15:00:51 +08003685bool ValidateFramebufferTexture2D(Context *context,
3686 GLenum target,
3687 GLenum attachment,
3688 GLenum textarget,
3689 GLuint texture,
3690 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003691{
He Yunchaoced53ae2016-11-29 15:00:51 +08003692 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3693 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003694 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3695 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003696 {
Jamie Madill437fa652016-05-03 15:13:24 -04003697 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003698 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003699 }
3700
3701 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003702 {
3703 return false;
3704 }
3705
Jamie Madill55ec3b12014-07-03 10:38:57 -04003706 if (texture != 0)
3707 {
3708 gl::Texture *tex = context->getTexture(texture);
3709 ASSERT(tex);
3710
Jamie Madill2a6564e2014-07-11 09:53:19 -04003711 const gl::Caps &caps = context->getCaps();
3712
Jamie Madill55ec3b12014-07-03 10:38:57 -04003713 switch (textarget)
3714 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003715 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003716 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003717 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003718 {
Jamie Madill437fa652016-05-03 15:13:24 -04003719 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003720 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003721 }
3722 if (tex->getTarget() != GL_TEXTURE_2D)
3723 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003724 context->handleError(Error(GL_INVALID_OPERATION,
3725 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003726 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003727 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003728 }
3729 break;
3730
He Yunchaoced53ae2016-11-29 15:00:51 +08003731 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3732 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3733 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3734 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3735 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3736 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003737 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003738 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003739 {
Jamie Madill437fa652016-05-03 15:13:24 -04003740 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003741 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003742 }
3743 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3744 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003745 context->handleError(Error(GL_INVALID_OPERATION,
3746 "Textarget must match the texture target type."));
3747 return false;
3748 }
3749 }
3750 break;
3751
3752 case GL_TEXTURE_2D_MULTISAMPLE:
3753 {
3754 if (context->getClientVersion() < ES_3_1)
3755 {
3756 context->handleError(Error(GL_INVALID_OPERATION,
3757 "Texture target requires at least OpenGL ES 3.1."));
3758 return false;
3759 }
3760
3761 if (level != 0)
3762 {
3763 context->handleError(
3764 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
3765 return false;
3766 }
3767 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
3768 {
3769 context->handleError(Error(GL_INVALID_OPERATION,
3770 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003771 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003772 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003773 }
3774 break;
3775
He Yunchaoced53ae2016-11-29 15:00:51 +08003776 default:
3777 context->handleError(Error(GL_INVALID_ENUM));
3778 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003779 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003780
Jamie Madilla3944d42016-07-22 22:13:26 -04003781 const Format &format = tex->getFormat(textarget, level);
3782 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003783 {
Jamie Madill437fa652016-05-03 15:13:24 -04003784 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003785 return false;
3786 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003787 }
3788
Jamie Madill570f7c82014-07-03 10:38:54 -04003789 return true;
3790}
3791
Geoff Langb1196682014-07-23 13:47:29 -04003792bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003793{
3794 if (program == 0)
3795 {
Jamie Madill437fa652016-05-03 15:13:24 -04003796 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003797 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003798 }
3799
Dian Xiang769769a2015-09-09 15:20:08 -07003800 gl::Program *programObject = GetValidProgram(context, program);
3801 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003802 {
3803 return false;
3804 }
3805
Jamie Madill0063c512014-08-25 15:47:53 -04003806 if (!programObject || !programObject->isLinked())
3807 {
Jamie Madill437fa652016-05-03 15:13:24 -04003808 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003809 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003810 }
3811
Geoff Lang7dd2e102014-11-10 15:19:26 -05003812 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003813 {
Jamie Madill437fa652016-05-03 15:13:24 -04003814 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003815 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003816 }
3817
Jamie Madill0063c512014-08-25 15:47:53 -04003818 return true;
3819}
3820
He Yunchaoced53ae2016-11-29 15:00:51 +08003821bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003822{
3823 return ValidateGetUniformBase(context, program, location);
3824}
3825
He Yunchaoced53ae2016-11-29 15:00:51 +08003826bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003827{
Jamie Madill78f41802014-08-25 15:47:55 -04003828 return ValidateGetUniformBase(context, program, location);
3829}
3830
Geoff Langf41d0ee2016-10-07 13:04:23 -04003831static bool ValidateSizedGetUniform(Context *context,
3832 GLuint program,
3833 GLint location,
3834 GLsizei bufSize,
3835 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003836{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003837 if (length)
3838 {
3839 *length = 0;
3840 }
3841
Jamie Madill78f41802014-08-25 15:47:55 -04003842 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003843 {
Jamie Madill78f41802014-08-25 15:47:55 -04003844 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003845 }
3846
Geoff Langf41d0ee2016-10-07 13:04:23 -04003847 if (bufSize < 0)
3848 {
3849 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3850 return false;
3851 }
3852
Jamie Madilla502c742014-08-28 17:19:13 -04003853 gl::Program *programObject = context->getProgram(program);
3854 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003855
Jamie Madill78f41802014-08-25 15:47:55 -04003856 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003857 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003858 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003859 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003860 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003861 context->handleError(
3862 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003863 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003864 }
3865
Geoff Langf41d0ee2016-10-07 13:04:23 -04003866 if (length)
3867 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003868 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003869 }
3870
Jamie Madill0063c512014-08-25 15:47:53 -04003871 return true;
3872}
3873
He Yunchaoced53ae2016-11-29 15:00:51 +08003874bool ValidateGetnUniformfvEXT(Context *context,
3875 GLuint program,
3876 GLint location,
3877 GLsizei bufSize,
3878 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003879{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003880 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003881}
3882
He Yunchaoced53ae2016-11-29 15:00:51 +08003883bool ValidateGetnUniformivEXT(Context *context,
3884 GLuint program,
3885 GLint location,
3886 GLsizei bufSize,
3887 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003888{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003889 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3890}
3891
3892bool ValidateGetUniformfvRobustANGLE(Context *context,
3893 GLuint program,
3894 GLint location,
3895 GLsizei bufSize,
3896 GLsizei *length,
3897 GLfloat *params)
3898{
3899 if (!ValidateRobustEntryPoint(context, bufSize))
3900 {
3901 return false;
3902 }
3903
3904 // bufSize is validated in ValidateSizedGetUniform
3905 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3906}
3907
3908bool ValidateGetUniformivRobustANGLE(Context *context,
3909 GLuint program,
3910 GLint location,
3911 GLsizei bufSize,
3912 GLsizei *length,
3913 GLint *params)
3914{
3915 if (!ValidateRobustEntryPoint(context, bufSize))
3916 {
3917 return false;
3918 }
3919
3920 // bufSize is validated in ValidateSizedGetUniform
3921 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3922}
3923
3924bool ValidateGetUniformuivRobustANGLE(Context *context,
3925 GLuint program,
3926 GLint location,
3927 GLsizei bufSize,
3928 GLsizei *length,
3929 GLuint *params)
3930{
3931 if (!ValidateRobustEntryPoint(context, bufSize))
3932 {
3933 return false;
3934 }
3935
3936 if (context->getClientMajorVersion() < 3)
3937 {
3938 context->handleError(
3939 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3940 return false;
3941 }
3942
3943 // bufSize is validated in ValidateSizedGetUniform
3944 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003945}
3946
He Yunchaoced53ae2016-11-29 15:00:51 +08003947bool ValidateDiscardFramebufferBase(Context *context,
3948 GLenum target,
3949 GLsizei numAttachments,
3950 const GLenum *attachments,
3951 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003952{
3953 if (numAttachments < 0)
3954 {
Jamie Madill437fa652016-05-03 15:13:24 -04003955 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003956 return false;
3957 }
3958
3959 for (GLsizei i = 0; i < numAttachments; ++i)
3960 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003961 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003962 {
3963 if (defaultFramebuffer)
3964 {
Jamie Madill437fa652016-05-03 15:13:24 -04003965 context->handleError(Error(
3966 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003967 return false;
3968 }
3969
3970 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3971 {
Jamie Madill437fa652016-05-03 15:13:24 -04003972 context->handleError(Error(GL_INVALID_OPERATION,
3973 "Requested color attachment is greater than the maximum "
3974 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003975 return false;
3976 }
3977 }
3978 else
3979 {
3980 switch (attachments[i])
3981 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003982 case GL_DEPTH_ATTACHMENT:
3983 case GL_STENCIL_ATTACHMENT:
3984 case GL_DEPTH_STENCIL_ATTACHMENT:
3985 if (defaultFramebuffer)
3986 {
3987 context->handleError(
3988 Error(GL_INVALID_ENUM,
3989 "Invalid attachment when the default framebuffer is bound"));
3990 return false;
3991 }
3992 break;
3993 case GL_COLOR:
3994 case GL_DEPTH:
3995 case GL_STENCIL:
3996 if (!defaultFramebuffer)
3997 {
3998 context->handleError(
3999 Error(GL_INVALID_ENUM,
4000 "Invalid attachment when the default framebuffer is not bound"));
4001 return false;
4002 }
4003 break;
4004 default:
4005 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07004006 return false;
Austin Kinross08332632015-05-05 13:35:47 -07004007 }
4008 }
4009 }
4010
4011 return true;
4012}
4013
Austin Kinross6ee1e782015-05-29 17:05:37 -07004014bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
4015{
4016 // Note that debug marker calls must not set error state
4017
4018 if (length < 0)
4019 {
4020 return false;
4021 }
4022
4023 if (marker == nullptr)
4024 {
4025 return false;
4026 }
4027
4028 return true;
4029}
4030
4031bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
4032{
4033 // Note that debug marker calls must not set error state
4034
4035 if (length < 0)
4036 {
4037 return false;
4038 }
4039
4040 if (length > 0 && marker == nullptr)
4041 {
4042 return false;
4043 }
4044
4045 return true;
4046}
4047
Geoff Langdcab33b2015-07-21 13:03:16 -04004048bool ValidateEGLImageTargetTexture2DOES(Context *context,
4049 egl::Display *display,
4050 GLenum target,
4051 egl::Image *image)
4052{
Geoff Langa8406172015-07-21 16:53:39 -04004053 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4054 {
Jamie Madill437fa652016-05-03 15:13:24 -04004055 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004056 return false;
4057 }
4058
4059 switch (target)
4060 {
4061 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004062 if (!context->getExtensions().eglImage)
4063 {
4064 context->handleError(Error(
4065 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4066 }
4067 break;
4068
4069 case GL_TEXTURE_EXTERNAL_OES:
4070 if (!context->getExtensions().eglImageExternal)
4071 {
4072 context->handleError(Error(
4073 GL_INVALID_ENUM,
4074 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4075 }
Geoff Langa8406172015-07-21 16:53:39 -04004076 break;
4077
4078 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004079 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004080 return false;
4081 }
4082
4083 if (!display->isValidImage(image))
4084 {
Jamie Madill437fa652016-05-03 15:13:24 -04004085 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004086 return false;
4087 }
4088
4089 if (image->getSamples() > 0)
4090 {
Jamie Madill437fa652016-05-03 15:13:24 -04004091 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004092 "cannot create a 2D texture from a multisampled EGL image."));
4093 return false;
4094 }
4095
Jamie Madilla3944d42016-07-22 22:13:26 -04004096 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004097 if (!textureCaps.texturable)
4098 {
Jamie Madill437fa652016-05-03 15:13:24 -04004099 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004100 "EGL image internal format is not supported as a texture."));
4101 return false;
4102 }
4103
Geoff Langdcab33b2015-07-21 13:03:16 -04004104 return true;
4105}
4106
4107bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4108 egl::Display *display,
4109 GLenum target,
4110 egl::Image *image)
4111{
Geoff Langa8406172015-07-21 16:53:39 -04004112 if (!context->getExtensions().eglImage)
4113 {
Jamie Madill437fa652016-05-03 15:13:24 -04004114 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004115 return false;
4116 }
4117
4118 switch (target)
4119 {
4120 case GL_RENDERBUFFER:
4121 break;
4122
4123 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004124 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004125 return false;
4126 }
4127
4128 if (!display->isValidImage(image))
4129 {
Jamie Madill437fa652016-05-03 15:13:24 -04004130 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004131 return false;
4132 }
4133
Jamie Madilla3944d42016-07-22 22:13:26 -04004134 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004135 if (!textureCaps.renderable)
4136 {
Jamie Madill437fa652016-05-03 15:13:24 -04004137 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004138 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4139 return false;
4140 }
4141
Geoff Langdcab33b2015-07-21 13:03:16 -04004142 return true;
4143}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004144
4145bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4146{
Geoff Lang36167ab2015-12-07 10:27:14 -05004147 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004148 {
4149 // The default VAO should always exist
4150 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004151 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004152 return false;
4153 }
4154
4155 return true;
4156}
4157
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004158bool ValidateLinkProgram(Context *context, GLuint program)
4159{
4160 if (context->hasActiveTransformFeedback(program))
4161 {
4162 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004163 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004164 "Cannot link program while program is associated with an active "
4165 "transform feedback object."));
4166 return false;
4167 }
4168 return true;
4169}
4170
Geoff Langc5629752015-12-07 16:29:04 -05004171bool ValidateProgramBinaryBase(Context *context,
4172 GLuint program,
4173 GLenum binaryFormat,
4174 const void *binary,
4175 GLint length)
4176{
4177 Program *programObject = GetValidProgram(context, program);
4178 if (programObject == nullptr)
4179 {
4180 return false;
4181 }
4182
4183 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4184 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4185 programBinaryFormats.end())
4186 {
Jamie Madill437fa652016-05-03 15:13:24 -04004187 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004188 return false;
4189 }
4190
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004191 if (context->hasActiveTransformFeedback(program))
4192 {
4193 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004194 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004195 "Cannot change program binary while program is associated with "
4196 "an active transform feedback object."));
4197 return false;
4198 }
4199
Geoff Langc5629752015-12-07 16:29:04 -05004200 return true;
4201}
4202
4203bool ValidateGetProgramBinaryBase(Context *context,
4204 GLuint program,
4205 GLsizei bufSize,
4206 GLsizei *length,
4207 GLenum *binaryFormat,
4208 void *binary)
4209{
4210 Program *programObject = GetValidProgram(context, program);
4211 if (programObject == nullptr)
4212 {
4213 return false;
4214 }
4215
4216 if (!programObject->isLinked())
4217 {
Jamie Madill437fa652016-05-03 15:13:24 -04004218 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004219 return false;
4220 }
4221
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004222 if (context->getCaps().programBinaryFormats.empty())
4223 {
4224 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4225 return false;
4226 }
4227
Geoff Langc5629752015-12-07 16:29:04 -05004228 return true;
4229}
Jamie Madillc29968b2016-01-20 11:17:23 -05004230
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004231bool ValidateUseProgram(Context *context, GLuint program)
4232{
4233 if (program != 0)
4234 {
4235 Program *programObject = context->getProgram(program);
4236 if (!programObject)
4237 {
4238 // ES 3.1.0 section 7.3 page 72
4239 if (context->getShader(program))
4240 {
Jamie Madill437fa652016-05-03 15:13:24 -04004241 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004242 Error(GL_INVALID_OPERATION,
4243 "Attempted to use a single shader instead of a shader program."));
4244 return false;
4245 }
4246 else
4247 {
Jamie Madill437fa652016-05-03 15:13:24 -04004248 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004249 return false;
4250 }
4251 }
4252 if (!programObject->isLinked())
4253 {
Jamie Madill437fa652016-05-03 15:13:24 -04004254 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004255 return false;
4256 }
4257 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004258 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004259 {
4260 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004261 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004262 Error(GL_INVALID_OPERATION,
4263 "Cannot change active program while transform feedback is unpaused."));
4264 return false;
4265 }
4266
4267 return true;
4268}
4269
Jamie Madillc29968b2016-01-20 11:17:23 -05004270bool ValidateCopyTexImage2D(ValidationContext *context,
4271 GLenum target,
4272 GLint level,
4273 GLenum internalformat,
4274 GLint x,
4275 GLint y,
4276 GLsizei width,
4277 GLsizei height,
4278 GLint border)
4279{
Martin Radev1be913c2016-07-11 17:59:16 +03004280 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004281 {
4282 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4283 0, x, y, width, height, border);
4284 }
4285
Martin Radev1be913c2016-07-11 17:59:16 +03004286 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004287 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4288 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004289}
Jamie Madillc29968b2016-01-20 11:17:23 -05004290
4291bool ValidateFramebufferRenderbuffer(Context *context,
4292 GLenum target,
4293 GLenum attachment,
4294 GLenum renderbuffertarget,
4295 GLuint renderbuffer)
4296{
4297 if (!ValidFramebufferTarget(target) ||
4298 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4299 {
Jamie Madill437fa652016-05-03 15:13:24 -04004300 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004301 return false;
4302 }
4303
4304 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4305 renderbuffertarget, renderbuffer);
4306}
4307
4308bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4309{
4310 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4311 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4312 {
Jamie Madill437fa652016-05-03 15:13:24 -04004313 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004314 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4315 return false;
4316 }
4317
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004318 ASSERT(context->getGLState().getDrawFramebuffer());
4319 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004320 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4321
4322 // This should come first before the check for the default frame buffer
4323 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4324 // rather than INVALID_OPERATION
4325 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4326 {
4327 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4328
4329 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004330 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4331 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004332 {
4333 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004334 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4335 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4336 // 3.1 is still a bit ambiguous about the error, but future specs are
4337 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004338 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004339 return false;
4340 }
4341 else if (bufs[colorAttachment] >= maxColorAttachment)
4342 {
Jamie Madill437fa652016-05-03 15:13:24 -04004343 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004344 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004345 return false;
4346 }
4347 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4348 frameBufferId != 0)
4349 {
4350 // INVALID_OPERATION-GL is bound to buffer and ith argument
4351 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004352 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004353 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4354 return false;
4355 }
4356 }
4357
4358 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4359 // and n is not 1 or bufs is bound to value other than BACK and NONE
4360 if (frameBufferId == 0)
4361 {
4362 if (n != 1)
4363 {
Jamie Madill437fa652016-05-03 15:13:24 -04004364 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004365 "n must be 1 when GL is bound to the default framebuffer"));
4366 return false;
4367 }
4368
4369 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4370 {
Jamie Madill437fa652016-05-03 15:13:24 -04004371 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004372 GL_INVALID_OPERATION,
4373 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4374 return false;
4375 }
4376 }
4377
4378 return true;
4379}
4380
4381bool ValidateCopyTexSubImage2D(Context *context,
4382 GLenum target,
4383 GLint level,
4384 GLint xoffset,
4385 GLint yoffset,
4386 GLint x,
4387 GLint y,
4388 GLsizei width,
4389 GLsizei height)
4390{
Martin Radev1be913c2016-07-11 17:59:16 +03004391 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004392 {
4393 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4394 yoffset, x, y, width, height, 0);
4395 }
4396
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004397 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4398 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004399}
4400
Geoff Lang496c02d2016-10-20 11:38:11 -07004401bool ValidateGetBufferPointervBase(Context *context,
4402 GLenum target,
4403 GLenum pname,
4404 GLsizei *length,
4405 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004406{
Geoff Lang496c02d2016-10-20 11:38:11 -07004407 if (length)
4408 {
4409 *length = 0;
4410 }
4411
4412 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4413 {
4414 context->handleError(
4415 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004416 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004417 return false;
4418 }
4419
Olli Etuaho4f667482016-03-30 15:56:35 +03004420 if (!ValidBufferTarget(context, target))
4421 {
Jamie Madill437fa652016-05-03 15:13:24 -04004422 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004423 return false;
4424 }
4425
Geoff Lang496c02d2016-10-20 11:38:11 -07004426 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004427 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004428 case GL_BUFFER_MAP_POINTER:
4429 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004430
Geoff Lang496c02d2016-10-20 11:38:11 -07004431 default:
4432 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4433 return false;
4434 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004435
4436 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4437 // target bound to zero generate an INVALID_OPERATION error."
4438 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004439 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004440 {
Jamie Madill437fa652016-05-03 15:13:24 -04004441 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004442 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4443 return false;
4444 }
4445
Geoff Lang496c02d2016-10-20 11:38:11 -07004446 if (length)
4447 {
4448 *length = 1;
4449 }
4450
Olli Etuaho4f667482016-03-30 15:56:35 +03004451 return true;
4452}
4453
4454bool ValidateUnmapBufferBase(Context *context, GLenum target)
4455{
4456 if (!ValidBufferTarget(context, target))
4457 {
Jamie Madill437fa652016-05-03 15:13:24 -04004458 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004459 return false;
4460 }
4461
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004462 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004463
4464 if (buffer == nullptr || !buffer->isMapped())
4465 {
Jamie Madill437fa652016-05-03 15:13:24 -04004466 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004467 return false;
4468 }
4469
4470 return true;
4471}
4472
4473bool ValidateMapBufferRangeBase(Context *context,
4474 GLenum target,
4475 GLintptr offset,
4476 GLsizeiptr length,
4477 GLbitfield access)
4478{
4479 if (!ValidBufferTarget(context, target))
4480 {
Jamie Madill437fa652016-05-03 15:13:24 -04004481 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004482 return false;
4483 }
4484
4485 if (offset < 0 || length < 0)
4486 {
Jamie Madill437fa652016-05-03 15:13:24 -04004487 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004488 return false;
4489 }
4490
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004491 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004492
4493 if (!buffer)
4494 {
Jamie Madill437fa652016-05-03 15:13:24 -04004495 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004496 return false;
4497 }
4498
4499 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004500 CheckedNumeric<size_t> checkedOffset(offset);
4501 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004502
Jamie Madille2e406c2016-06-02 13:04:10 -04004503 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004504 {
Jamie Madill437fa652016-05-03 15:13:24 -04004505 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004506 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4507 return false;
4508 }
4509
4510 // Check for invalid bits in the mask
4511 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4512 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4513 GL_MAP_UNSYNCHRONIZED_BIT;
4514
4515 if (access & ~(allAccessBits))
4516 {
Jamie Madill437fa652016-05-03 15:13:24 -04004517 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004518 return false;
4519 }
4520
4521 if (length == 0)
4522 {
Jamie Madill437fa652016-05-03 15:13:24 -04004523 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004524 return false;
4525 }
4526
4527 if (buffer->isMapped())
4528 {
Jamie Madill437fa652016-05-03 15:13:24 -04004529 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004530 return false;
4531 }
4532
4533 // Check for invalid bit combinations
4534 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4535 {
Jamie Madill437fa652016-05-03 15:13:24 -04004536 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004537 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4538 return false;
4539 }
4540
4541 GLbitfield writeOnlyBits =
4542 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4543
4544 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4545 {
Jamie Madill437fa652016-05-03 15:13:24 -04004546 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004547 "Invalid access bits when mapping buffer for reading: 0x%X.",
4548 access));
4549 return false;
4550 }
4551
4552 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4553 {
Jamie Madill437fa652016-05-03 15:13:24 -04004554 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004555 GL_INVALID_OPERATION,
4556 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4557 return false;
4558 }
4559 return true;
4560}
4561
4562bool ValidateFlushMappedBufferRangeBase(Context *context,
4563 GLenum target,
4564 GLintptr offset,
4565 GLsizeiptr length)
4566{
4567 if (offset < 0 || length < 0)
4568 {
Jamie Madill437fa652016-05-03 15:13:24 -04004569 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004570 return false;
4571 }
4572
4573 if (!ValidBufferTarget(context, target))
4574 {
Jamie Madill437fa652016-05-03 15:13:24 -04004575 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004576 return false;
4577 }
4578
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004579 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004580
4581 if (buffer == nullptr)
4582 {
Jamie Madill437fa652016-05-03 15:13:24 -04004583 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004584 return false;
4585 }
4586
4587 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4588 {
Jamie Madill437fa652016-05-03 15:13:24 -04004589 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004590 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4591 return false;
4592 }
4593
4594 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004595 CheckedNumeric<size_t> checkedOffset(offset);
4596 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004597
Jamie Madille2e406c2016-06-02 13:04:10 -04004598 if (!checkedSize.IsValid() ||
4599 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004600 {
Jamie Madill437fa652016-05-03 15:13:24 -04004601 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004602 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4603 return false;
4604 }
4605
4606 return true;
4607}
4608
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004609bool ValidateGenerateMipmap(Context *context, GLenum target)
4610{
4611 if (!ValidTextureTarget(context, target))
4612 {
4613 context->handleError(Error(GL_INVALID_ENUM));
4614 return false;
4615 }
4616
4617 Texture *texture = context->getTargetTexture(target);
4618
4619 if (texture == nullptr)
4620 {
4621 context->handleError(Error(GL_INVALID_OPERATION));
4622 return false;
4623 }
4624
4625 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4626
4627 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4628 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4629 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4630 {
4631 context->handleError(Error(GL_INVALID_OPERATION));
4632 return false;
4633 }
4634
Jamie Madilla3944d42016-07-22 22:13:26 -04004635 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4636 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4637 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004638
4639 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4640 // unsized formats or that are color renderable and filterable. Since we do not track if
4641 // the texture was created with sized or unsized format (only sized formats are stored),
4642 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4643 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4644 // textures since they're the only texture format that can be created with unsized formats
4645 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4646 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004647 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4648 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004649 {
4650 context->handleError(Error(GL_INVALID_OPERATION));
4651 return false;
4652 }
4653
4654 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004655 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004656 {
4657 context->handleError(Error(GL_INVALID_OPERATION));
4658 return false;
4659 }
4660
4661 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004662 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004663 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4664 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4665 {
Geoff Lang55482a12016-11-21 16:54:01 -05004666 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004667 context->handleError(Error(GL_INVALID_OPERATION));
4668 return false;
4669 }
4670
4671 // Cube completeness check
4672 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4673 {
4674 context->handleError(Error(GL_INVALID_OPERATION));
4675 return false;
4676 }
4677
4678 return true;
4679}
4680
Olli Etuaho41997e72016-03-10 13:38:39 +02004681bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4682{
4683 return ValidateGenOrDelete(context, n);
4684}
4685
4686bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4687{
4688 return ValidateGenOrDelete(context, n);
4689}
4690
4691bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4692{
4693 return ValidateGenOrDelete(context, n);
4694}
4695
4696bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4697{
4698 return ValidateGenOrDelete(context, n);
4699}
4700
4701bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4702{
4703 return ValidateGenOrDelete(context, n);
4704}
4705
4706bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4707{
4708 return ValidateGenOrDelete(context, n);
4709}
4710
4711bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4712{
4713 return ValidateGenOrDelete(context, n);
4714}
4715
4716bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4717{
4718 return ValidateGenOrDelete(context, n);
4719}
4720
4721bool ValidateGenOrDelete(Context *context, GLint n)
4722{
4723 if (n < 0)
4724 {
Jamie Madill437fa652016-05-03 15:13:24 -04004725 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004726 return false;
4727 }
4728 return true;
4729}
4730
Geoff Langf41a7152016-09-19 15:11:17 -04004731bool ValidateEnable(Context *context, GLenum cap)
4732{
4733 if (!ValidCap(context, cap, false))
4734 {
4735 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4736 return false;
4737 }
4738
4739 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4740 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4741 {
4742 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4743 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4744
4745 // We also output an error message to the debugger window if tracing is active, so that
4746 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05004747 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04004748 return false;
4749 }
4750
4751 return true;
4752}
4753
4754bool ValidateDisable(Context *context, GLenum cap)
4755{
4756 if (!ValidCap(context, cap, false))
4757 {
4758 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4759 return false;
4760 }
4761
4762 return true;
4763}
4764
4765bool ValidateIsEnabled(Context *context, GLenum cap)
4766{
4767 if (!ValidCap(context, cap, true))
4768 {
4769 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4770 return false;
4771 }
4772
4773 return true;
4774}
4775
Geoff Langff5b2d52016-09-07 11:32:23 -04004776bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4777{
4778 if (!context->getExtensions().robustClientMemory)
4779 {
4780 context->handleError(
4781 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4782 return false;
4783 }
4784
4785 if (bufSize < 0)
4786 {
4787 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4788 return false;
4789 }
4790
4791 return true;
4792}
4793
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004794bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4795{
4796 if (bufSize < numParams)
4797 {
4798 context->handleError(Error(GL_INVALID_OPERATION,
4799 "%u parameters are required but %i were provided.", numParams,
4800 bufSize));
4801 return false;
4802 }
4803
4804 return true;
4805}
4806
Geoff Langff5b2d52016-09-07 11:32:23 -04004807bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4808 GLenum target,
4809 GLenum attachment,
4810 GLenum pname,
4811 GLsizei *numParams)
4812{
4813 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4814 *numParams = 1;
4815
4816 if (!ValidFramebufferTarget(target))
4817 {
4818 context->handleError(Error(GL_INVALID_ENUM));
4819 return false;
4820 }
4821
4822 int clientVersion = context->getClientMajorVersion();
4823
4824 switch (pname)
4825 {
4826 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4827 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4828 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4829 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4830 break;
4831
4832 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4833 if (clientVersion < 3 && !context->getExtensions().sRGB)
4834 {
4835 context->handleError(Error(GL_INVALID_ENUM));
4836 return false;
4837 }
4838 break;
4839
4840 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4841 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4842 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4843 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4844 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4845 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4846 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4847 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4848 if (clientVersion < 3)
4849 {
4850 context->handleError(Error(GL_INVALID_ENUM));
4851 return false;
4852 }
4853 break;
4854
4855 default:
4856 context->handleError(Error(GL_INVALID_ENUM));
4857 return false;
4858 }
4859
4860 // Determine if the attachment is a valid enum
4861 switch (attachment)
4862 {
4863 case GL_BACK:
4864 case GL_FRONT:
4865 case GL_DEPTH:
4866 case GL_STENCIL:
4867 case GL_DEPTH_STENCIL_ATTACHMENT:
4868 if (clientVersion < 3)
4869 {
4870 context->handleError(Error(GL_INVALID_ENUM));
4871 return false;
4872 }
4873 break;
4874
4875 case GL_DEPTH_ATTACHMENT:
4876 case GL_STENCIL_ATTACHMENT:
4877 break;
4878
4879 default:
4880 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4881 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4882 {
4883 context->handleError(Error(GL_INVALID_ENUM));
4884 return false;
4885 }
4886 break;
4887 }
4888
4889 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4890 ASSERT(framebuffer);
4891
4892 if (framebuffer->id() == 0)
4893 {
4894 if (clientVersion < 3)
4895 {
4896 context->handleError(Error(GL_INVALID_OPERATION));
4897 return false;
4898 }
4899
4900 switch (attachment)
4901 {
4902 case GL_BACK:
4903 case GL_DEPTH:
4904 case GL_STENCIL:
4905 break;
4906
4907 default:
4908 context->handleError(Error(GL_INVALID_OPERATION));
4909 return false;
4910 }
4911 }
4912 else
4913 {
4914 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4915 {
4916 // Valid attachment query
4917 }
4918 else
4919 {
4920 switch (attachment)
4921 {
4922 case GL_DEPTH_ATTACHMENT:
4923 case GL_STENCIL_ATTACHMENT:
4924 break;
4925
4926 case GL_DEPTH_STENCIL_ATTACHMENT:
4927 if (!framebuffer->hasValidDepthStencil())
4928 {
4929 context->handleError(Error(GL_INVALID_OPERATION));
4930 return false;
4931 }
4932 break;
4933
4934 default:
4935 context->handleError(Error(GL_INVALID_OPERATION));
4936 return false;
4937 }
4938 }
4939 }
4940
4941 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4942 if (attachmentObject)
4943 {
4944 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4945 attachmentObject->type() == GL_TEXTURE ||
4946 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4947
4948 switch (pname)
4949 {
4950 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4951 if (attachmentObject->type() != GL_RENDERBUFFER &&
4952 attachmentObject->type() != GL_TEXTURE)
4953 {
4954 context->handleError(Error(GL_INVALID_ENUM));
4955 return false;
4956 }
4957 break;
4958
4959 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4960 if (attachmentObject->type() != GL_TEXTURE)
4961 {
4962 context->handleError(Error(GL_INVALID_ENUM));
4963 return false;
4964 }
4965 break;
4966
4967 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4968 if (attachmentObject->type() != GL_TEXTURE)
4969 {
4970 context->handleError(Error(GL_INVALID_ENUM));
4971 return false;
4972 }
4973 break;
4974
4975 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4976 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4977 {
4978 context->handleError(Error(GL_INVALID_OPERATION));
4979 return false;
4980 }
4981 break;
4982
4983 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4984 if (attachmentObject->type() != GL_TEXTURE)
4985 {
4986 context->handleError(Error(GL_INVALID_ENUM));
4987 return false;
4988 }
4989 break;
4990
4991 default:
4992 break;
4993 }
4994 }
4995 else
4996 {
4997 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4998 // is NONE, then querying any other pname will generate INVALID_ENUM.
4999
5000 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
5001 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
5002 // INVALID_OPERATION for all other pnames
5003
5004 switch (pname)
5005 {
5006 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
5007 break;
5008
5009 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
5010 if (clientVersion < 3)
5011 {
5012 context->handleError(Error(GL_INVALID_ENUM));
5013 return false;
5014 }
5015 break;
5016
5017 default:
5018 if (clientVersion < 3)
5019 {
5020 context->handleError(Error(GL_INVALID_ENUM));
5021 return false;
5022 }
5023 else
5024 {
5025 context->handleError(Error(GL_INVALID_OPERATION));
5026 return false;
5027 }
5028 }
5029 }
5030
5031 return true;
5032}
5033
5034bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5035 GLenum target,
5036 GLenum attachment,
5037 GLenum pname,
5038 GLsizei bufSize,
5039 GLsizei *numParams)
5040{
5041 if (!ValidateRobustEntryPoint(context, bufSize))
5042 {
5043 return false;
5044 }
5045
5046 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5047 {
5048 return false;
5049 }
5050
5051 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5052 {
5053 return false;
5054 }
5055
5056 return true;
5057}
5058
5059bool ValidateGetBufferParameteriv(ValidationContext *context,
5060 GLenum target,
5061 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005062 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005063{
Geoff Langebebe1c2016-10-14 12:01:31 -04005064 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005065}
5066
5067bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5068 GLenum target,
5069 GLenum pname,
5070 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005071 GLsizei *length,
5072 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005073{
5074 if (!ValidateRobustEntryPoint(context, bufSize))
5075 {
5076 return false;
5077 }
5078
Geoff Langebebe1c2016-10-14 12:01:31 -04005079 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005080 {
5081 return false;
5082 }
5083
Geoff Langebebe1c2016-10-14 12:01:31 -04005084 if (!ValidateRobustBufferSize(context, bufSize, *length))
5085 {
5086 return false;
5087 }
5088
5089 return true;
5090}
5091
5092bool ValidateGetBufferParameteri64v(ValidationContext *context,
5093 GLenum target,
5094 GLenum pname,
5095 GLint64 *params)
5096{
5097 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5098}
5099
5100bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5101 GLenum target,
5102 GLenum pname,
5103 GLsizei bufSize,
5104 GLsizei *length,
5105 GLint64 *params)
5106{
5107 if (!ValidateRobustEntryPoint(context, bufSize))
5108 {
5109 return false;
5110 }
5111
5112 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5113 {
5114 return false;
5115 }
5116
5117 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005118 {
5119 return false;
5120 }
5121
5122 return true;
5123}
5124
5125bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5126{
5127 // Currently, all GetProgramiv queries return 1 parameter
5128 *numParams = 1;
5129
5130 Program *programObject = GetValidProgram(context, program);
5131 if (!programObject)
5132 {
5133 return false;
5134 }
5135
5136 switch (pname)
5137 {
5138 case GL_DELETE_STATUS:
5139 case GL_LINK_STATUS:
5140 case GL_VALIDATE_STATUS:
5141 case GL_INFO_LOG_LENGTH:
5142 case GL_ATTACHED_SHADERS:
5143 case GL_ACTIVE_ATTRIBUTES:
5144 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5145 case GL_ACTIVE_UNIFORMS:
5146 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5147 break;
5148
5149 case GL_PROGRAM_BINARY_LENGTH:
5150 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5151 {
5152 context->handleError(Error(GL_INVALID_ENUM,
5153 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5154 "GL_OES_get_program_binary or ES 3.0."));
5155 return false;
5156 }
5157 break;
5158
5159 case GL_ACTIVE_UNIFORM_BLOCKS:
5160 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5161 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5162 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5163 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5164 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5165 if (context->getClientMajorVersion() < 3)
5166 {
5167 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5168 return false;
5169 }
5170 break;
5171
5172 default:
5173 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5174 return false;
5175 }
5176
5177 return true;
5178}
5179
5180bool ValidateGetProgramivRobustANGLE(Context *context,
5181 GLuint program,
5182 GLenum pname,
5183 GLsizei bufSize,
5184 GLsizei *numParams)
5185{
5186 if (!ValidateRobustEntryPoint(context, bufSize))
5187 {
5188 return false;
5189 }
5190
5191 if (!ValidateGetProgramiv(context, program, pname, numParams))
5192 {
5193 return false;
5194 }
5195
5196 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5197 {
5198 return false;
5199 }
5200
5201 return true;
5202}
5203
Geoff Lang740d9022016-10-07 11:20:52 -04005204bool ValidateGetRenderbufferParameteriv(Context *context,
5205 GLenum target,
5206 GLenum pname,
5207 GLint *params)
5208{
5209 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5210}
5211
5212bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5213 GLenum target,
5214 GLenum pname,
5215 GLsizei bufSize,
5216 GLsizei *length,
5217 GLint *params)
5218{
5219 if (!ValidateRobustEntryPoint(context, bufSize))
5220 {
5221 return false;
5222 }
5223
5224 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5225 {
5226 return false;
5227 }
5228
5229 if (!ValidateRobustBufferSize(context, bufSize, *length))
5230 {
5231 return false;
5232 }
5233
5234 return true;
5235}
5236
Geoff Langd7d0ed32016-10-07 11:33:51 -04005237bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5238{
5239 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5240}
5241
5242bool ValidateGetShaderivRobustANGLE(Context *context,
5243 GLuint shader,
5244 GLenum pname,
5245 GLsizei bufSize,
5246 GLsizei *length,
5247 GLint *params)
5248{
5249 if (!ValidateRobustEntryPoint(context, bufSize))
5250 {
5251 return false;
5252 }
5253
5254 if (!ValidateGetShaderivBase(context, shader, pname, length))
5255 {
5256 return false;
5257 }
5258
5259 if (!ValidateRobustBufferSize(context, bufSize, *length))
5260 {
5261 return false;
5262 }
5263
5264 return true;
5265}
5266
Geoff Langc1984ed2016-10-07 12:41:00 -04005267bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5268{
5269 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5270}
5271
5272bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5273 GLenum target,
5274 GLenum pname,
5275 GLsizei bufSize,
5276 GLsizei *length,
5277 GLfloat *params)
5278{
5279 if (!ValidateRobustEntryPoint(context, bufSize))
5280 {
5281 return false;
5282 }
5283
5284 if (!ValidateGetTexParameterBase(context, target, pname, length))
5285 {
5286 return false;
5287 }
5288
5289 if (!ValidateRobustBufferSize(context, bufSize, *length))
5290 {
5291 return false;
5292 }
5293
5294 return true;
5295}
5296
5297bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5298{
5299 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5300}
5301
5302bool ValidateGetTexParameterivRobustANGLE(Context *context,
5303 GLenum target,
5304 GLenum pname,
5305 GLsizei bufSize,
5306 GLsizei *length,
5307 GLint *params)
5308{
5309 if (!ValidateRobustEntryPoint(context, bufSize))
5310 {
5311 return false;
5312 }
5313
5314 if (!ValidateGetTexParameterBase(context, target, pname, length))
5315 {
5316 return false;
5317 }
5318
5319 if (!ValidateRobustBufferSize(context, bufSize, *length))
5320 {
5321 return false;
5322 }
5323
5324 return true;
5325}
5326
5327bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5328{
5329 return ValidateTexParameterBase(context, target, pname, -1, &param);
5330}
5331
5332bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5333{
5334 return ValidateTexParameterBase(context, target, pname, -1, params);
5335}
5336
5337bool ValidateTexParameterfvRobustANGLE(Context *context,
5338 GLenum target,
5339 GLenum pname,
5340 GLsizei bufSize,
5341 const GLfloat *params)
5342{
5343 if (!ValidateRobustEntryPoint(context, bufSize))
5344 {
5345 return false;
5346 }
5347
5348 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5349}
5350
5351bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5352{
5353 return ValidateTexParameterBase(context, target, pname, -1, &param);
5354}
5355
5356bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5357{
5358 return ValidateTexParameterBase(context, target, pname, -1, params);
5359}
5360
5361bool ValidateTexParameterivRobustANGLE(Context *context,
5362 GLenum target,
5363 GLenum pname,
5364 GLsizei bufSize,
5365 const GLint *params)
5366{
5367 if (!ValidateRobustEntryPoint(context, bufSize))
5368 {
5369 return false;
5370 }
5371
5372 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5373}
5374
5375bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5376{
5377 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5378}
5379
5380bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5381 GLuint sampler,
5382 GLenum pname,
5383 GLuint bufSize,
5384 GLsizei *length,
5385 GLfloat *params)
5386{
5387 if (!ValidateRobustEntryPoint(context, bufSize))
5388 {
5389 return false;
5390 }
5391
5392 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5393 {
5394 return false;
5395 }
5396
5397 if (!ValidateRobustBufferSize(context, bufSize, *length))
5398 {
5399 return false;
5400 }
5401
5402 return true;
5403}
5404
5405bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5406{
5407 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5408}
5409
5410bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5411 GLuint sampler,
5412 GLenum pname,
5413 GLuint bufSize,
5414 GLsizei *length,
5415 GLint *params)
5416{
5417 if (!ValidateRobustEntryPoint(context, bufSize))
5418 {
5419 return false;
5420 }
5421
5422 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5423 {
5424 return false;
5425 }
5426
5427 if (!ValidateRobustBufferSize(context, bufSize, *length))
5428 {
5429 return false;
5430 }
5431
5432 return true;
5433}
5434
5435bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5436{
5437 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5438}
5439
5440bool ValidateSamplerParameterfv(Context *context,
5441 GLuint sampler,
5442 GLenum pname,
5443 const GLfloat *params)
5444{
5445 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5446}
5447
5448bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5449 GLuint sampler,
5450 GLenum pname,
5451 GLsizei bufSize,
5452 const GLfloat *params)
5453{
5454 if (!ValidateRobustEntryPoint(context, bufSize))
5455 {
5456 return false;
5457 }
5458
5459 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5460}
5461
5462bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5463{
5464 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5465}
5466
5467bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5468{
5469 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5470}
5471
5472bool ValidateSamplerParameterivRobustANGLE(Context *context,
5473 GLuint sampler,
5474 GLenum pname,
5475 GLsizei bufSize,
5476 const GLint *params)
5477{
5478 if (!ValidateRobustEntryPoint(context, bufSize))
5479 {
5480 return false;
5481 }
5482
5483 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5484}
5485
Geoff Lang0b031062016-10-13 14:30:04 -04005486bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5487{
5488 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5489}
5490
5491bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5492 GLuint index,
5493 GLenum pname,
5494 GLsizei bufSize,
5495 GLsizei *length,
5496 GLfloat *params)
5497{
5498 if (!ValidateRobustEntryPoint(context, bufSize))
5499 {
5500 return false;
5501 }
5502
5503 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5504 {
5505 return false;
5506 }
5507
5508 if (!ValidateRobustBufferSize(context, bufSize, *length))
5509 {
5510 return false;
5511 }
5512
5513 return true;
5514}
5515
5516bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5517{
5518 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5519}
5520
5521bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5522 GLuint index,
5523 GLenum pname,
5524 GLsizei bufSize,
5525 GLsizei *length,
5526 GLint *params)
5527{
5528 if (!ValidateRobustEntryPoint(context, bufSize))
5529 {
5530 return false;
5531 }
5532
5533 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5534 {
5535 return false;
5536 }
5537
5538 if (!ValidateRobustBufferSize(context, bufSize, *length))
5539 {
5540 return false;
5541 }
5542
5543 return true;
5544}
5545
5546bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5547{
5548 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5549}
5550
5551bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5552 GLuint index,
5553 GLenum pname,
5554 GLsizei bufSize,
5555 GLsizei *length,
5556 void **pointer)
5557{
5558 if (!ValidateRobustEntryPoint(context, bufSize))
5559 {
5560 return false;
5561 }
5562
5563 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5564 {
5565 return false;
5566 }
5567
5568 if (!ValidateRobustBufferSize(context, bufSize, *length))
5569 {
5570 return false;
5571 }
5572
5573 return true;
5574}
5575
5576bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5577{
5578 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5579}
5580
5581bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5582 GLuint index,
5583 GLenum pname,
5584 GLsizei bufSize,
5585 GLsizei *length,
5586 GLint *params)
5587{
5588 if (!ValidateRobustEntryPoint(context, bufSize))
5589 {
5590 return false;
5591 }
5592
5593 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5594 {
5595 return false;
5596 }
5597
5598 if (!ValidateRobustBufferSize(context, bufSize, *length))
5599 {
5600 return false;
5601 }
5602
5603 return true;
5604}
5605
5606bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5607{
5608 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5609}
5610
5611bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5612 GLuint index,
5613 GLenum pname,
5614 GLsizei bufSize,
5615 GLsizei *length,
5616 GLuint *params)
5617{
5618 if (!ValidateRobustEntryPoint(context, bufSize))
5619 {
5620 return false;
5621 }
5622
5623 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5624 {
5625 return false;
5626 }
5627
5628 if (!ValidateRobustBufferSize(context, bufSize, *length))
5629 {
5630 return false;
5631 }
5632
5633 return true;
5634}
5635
Geoff Lang6899b872016-10-14 11:30:13 -04005636bool ValidateGetActiveUniformBlockiv(Context *context,
5637 GLuint program,
5638 GLuint uniformBlockIndex,
5639 GLenum pname,
5640 GLint *params)
5641{
5642 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5643}
5644
5645bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5646 GLuint program,
5647 GLuint uniformBlockIndex,
5648 GLenum pname,
5649 GLsizei bufSize,
5650 GLsizei *length,
5651 GLint *params)
5652{
5653 if (!ValidateRobustEntryPoint(context, bufSize))
5654 {
5655 return false;
5656 }
5657
5658 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5659 {
5660 return false;
5661 }
5662
5663 if (!ValidateRobustBufferSize(context, bufSize, *length))
5664 {
5665 return false;
5666 }
5667
5668 return true;
5669}
5670
Geoff Lang0a9661f2016-10-20 10:59:20 -07005671bool ValidateGetInternalFormativ(Context *context,
5672 GLenum target,
5673 GLenum internalformat,
5674 GLenum pname,
5675 GLsizei bufSize,
5676 GLint *params)
5677{
5678 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5679 nullptr);
5680}
5681
5682bool ValidateGetInternalFormativRobustANGLE(Context *context,
5683 GLenum target,
5684 GLenum internalformat,
5685 GLenum pname,
5686 GLsizei bufSize,
5687 GLsizei *length,
5688 GLint *params)
5689{
5690 if (!ValidateRobustEntryPoint(context, bufSize))
5691 {
5692 return false;
5693 }
5694
5695 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5696 {
5697 return false;
5698 }
5699
5700 if (!ValidateRobustBufferSize(context, bufSize, *length))
5701 {
5702 return false;
5703 }
5704
5705 return true;
5706}
5707
Jamie Madillc29968b2016-01-20 11:17:23 -05005708} // namespace gl