blob: 4a9081ab16caf02a7c808be987840c2132a7080d [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES2.h"
12#include "libANGLE/validationES3.h"
13#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040014#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Texture.h"
16#include "libANGLE/Framebuffer.h"
17#include "libANGLE/FramebufferAttachment.h"
18#include "libANGLE/formatutils.h"
Geoff Langa8406172015-07-21 16:53:39 -040019#include "libANGLE/Image.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/Query.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050021#include "libANGLE/Program.h"
22#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/TransformFeedback.h"
24#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025
26#include "common/mathutil.h"
27#include "common/utilities.h"
28
Jamie Madille2e406c2016-06-02 13:04:10 -040029using namespace angle;
30
Geoff Lange8ebe7f2013-08-05 15:03:13 -040031namespace gl
32{
Jamie Madille79b1e12015-11-04 16:36:37 -050033const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
34
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Corentin Wallez92db6942016-12-09 13:10:36 -050037bool ValidateDrawAttribs(ValidationContext *context,
38 GLint primcount,
39 GLint maxVertex,
40 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040041{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070042 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040043 const gl::Program *program = state.getProgram();
44
Corentin Wallez327411e2016-12-09 11:09:17 -050045 bool webglCompatibility = context->getExtensions().webglCompatibility;
46
He Yunchaoced53ae2016-11-29 15:00:51 +080047 const VertexArray *vao = state.getVertexArray();
48 const auto &vertexAttribs = vao->getVertexAttributes();
49 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040050 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
51 {
52 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallezfd456442016-12-21 17:57:00 -050053 if (!program->isAttribLocationActive(attributeIndex) || !attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040054 {
Corentin Wallezfd456442016-12-21 17:57:00 -050055 continue;
56 }
Jamie Madill1ca74672015-07-21 15:14:11 -040057
Corentin Wallezfd456442016-12-21 17:57:00 -050058 // If we have no buffer, then we either get an error, or there are no more checks to be done.
59 gl::Buffer *buffer = attrib.buffer.get();
60 if (!buffer)
61 {
62 if (webglCompatibility)
Corentin Wallez327411e2016-12-09 11:09:17 -050063 {
64 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050065 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
66 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
67 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
68 // error.
Corentin Wallez327411e2016-12-09 11:09:17 -050069 context->handleError(
70 Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer."));
Corentin Wallezfd456442016-12-21 17:57:00 -050071 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050072 }
Corentin Wallezfd456442016-12-21 17:57:00 -050073 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040074 {
75 // This is an application error that would normally result in a crash,
76 // but we catch it and return an error
Corentin Wallezfd456442016-12-21 17:57:00 -050077 context->handleError(
78 Error(GL_INVALID_OPERATION,
79 "An enabled vertex array has no buffer and no pointer."));
Jamie Madill1ca74672015-07-21 15:14:11 -040080 return false;
81 }
Corentin Wallezfd456442016-12-21 17:57:00 -050082 continue;
83 }
84
85 // If we're drawing zero vertices, we have enough data.
86 if (vertexCount <= 0 || primcount <= 0)
87 {
88 continue;
89 }
90
91 GLint maxVertexElement = 0;
92 if (attrib.divisor == 0)
93 {
94 maxVertexElement = maxVertex;
95 }
96 else
97 {
98 maxVertexElement = (primcount - 1) / attrib.divisor;
99 }
100
101 // We do manual overflow checks here instead of using safe_math.h because it was
102 // a bottleneck. Thanks to some properties of GL we know inequalities that can
103 // help us make the overflow checks faster.
104
105 // The max possible attribSize is 16 for a vector of 4 32 bit values.
106 constexpr uint64_t kMaxAttribSize = 16;
107 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
108 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
109
110 // We know attribStride is given as a GLsizei which is typedefed to int.
111 // We also know an upper bound for attribSize.
112 static_assert(std::is_same<int, GLsizei>::value, "");
113 uint64_t attribStride = ComputeVertexAttributeStride(attrib);
114 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
115 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
116
117 // Computing the max offset using uint64_t without attrib.offset is overflow
118 // safe. Note: Last vertex element does not take the full stride!
119 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
120 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
121
122 // An overflow can happen when adding the offset, check for it.
123 uint64_t attribOffset = attrib.offset;
124 if (attribDataSizeNoOffset > kUint64Max - attrib.offset)
125 {
126 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
127 return false;
128 }
129 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
130
131 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
132 // We can return INVALID_OPERATION if our vertex attribute does not have
133 // enough backing data.
134 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
135 {
136 context->handleError(Error(GL_INVALID_OPERATION,
137 "Vertex buffer is not big enough for the draw call"));
138 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400139 }
140 }
141
142 return true;
143}
144
Geoff Langf607c602016-09-21 11:46:48 -0400145bool ValidReadPixelsFormatType(ValidationContext *context,
146 GLenum framebufferComponentType,
147 GLenum format,
148 GLenum type)
149{
150 switch (framebufferComponentType)
151 {
152 case GL_UNSIGNED_NORMALIZED:
153 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
154 // ReadPixels with BGRA even if the extension is not present
155 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
156 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
157 type == GL_UNSIGNED_BYTE);
158
159 case GL_SIGNED_NORMALIZED:
160 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
161
162 case GL_INT:
163 return (format == GL_RGBA_INTEGER && type == GL_INT);
164
165 case GL_UNSIGNED_INT:
166 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
167
168 case GL_FLOAT:
169 return (format == GL_RGBA && type == GL_FLOAT);
170
171 default:
172 UNREACHABLE();
173 return false;
174 }
175}
176
Geoff Langf41a7152016-09-19 15:11:17 -0400177bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500178{
179 switch (cap)
180 {
Geoff Langf41a7152016-09-19 15:11:17 -0400181 // EXT_multisample_compatibility
182 case GL_MULTISAMPLE_EXT:
183 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
184 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300185
Geoff Langf41a7152016-09-19 15:11:17 -0400186 case GL_CULL_FACE:
187 case GL_POLYGON_OFFSET_FILL:
188 case GL_SAMPLE_ALPHA_TO_COVERAGE:
189 case GL_SAMPLE_COVERAGE:
190 case GL_SCISSOR_TEST:
191 case GL_STENCIL_TEST:
192 case GL_DEPTH_TEST:
193 case GL_BLEND:
194 case GL_DITHER:
195 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500196
Geoff Langf41a7152016-09-19 15:11:17 -0400197 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
198 case GL_RASTERIZER_DISCARD:
199 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500200
Geoff Langf41a7152016-09-19 15:11:17 -0400201 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
202 case GL_DEBUG_OUTPUT:
203 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500204
Geoff Langf41a7152016-09-19 15:11:17 -0400205 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
206 return queryOnly && context->getExtensions().bindGeneratesResource;
207
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700208 case GL_FRAMEBUFFER_SRGB_EXT:
209 return context->getExtensions().sRGBWriteControl;
210
Geoff Lang3b573612016-10-31 14:08:10 -0400211 case GL_SAMPLE_MASK:
Geoff Lang3b573612016-10-31 14:08:10 -0400212 return context->getClientVersion() >= Version(3, 1);
213
Geoff Langf41a7152016-09-19 15:11:17 -0400214 default:
215 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500216 }
217}
218
Geoff Lang62fce5b2016-09-30 10:46:35 -0400219bool ValidateReadPixelsBase(ValidationContext *context,
220 GLint x,
221 GLint y,
222 GLsizei width,
223 GLsizei height,
224 GLenum format,
225 GLenum type,
226 GLsizei bufSize,
227 GLsizei *length,
228 GLvoid *pixels)
229{
230 if (length != nullptr)
231 {
232 *length = 0;
233 }
234
235 if (width < 0 || height < 0)
236 {
237 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
238 return false;
239 }
240
241 auto readFramebuffer = context->getGLState().getReadFramebuffer();
242
243 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
244 {
245 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
246 return false;
247 }
248
249 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
250 {
251 context->handleError(Error(GL_INVALID_OPERATION));
252 return false;
253 }
254
255 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
256 ASSERT(framebuffer);
257
258 if (framebuffer->getReadBufferState() == GL_NONE)
259 {
260 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
261 return false;
262 }
263
264 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500265 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
266 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
267 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
268 // situation is an application error that would lead to a crash in ANGLE.
269 if (readBuffer == nullptr)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400270 {
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500271 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
Geoff Lang62fce5b2016-09-30 10:46:35 -0400272 return false;
273 }
274
275 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
276 GLenum currentType = framebuffer->getImplementationColorReadType();
277 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
278
279 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
280 bool validFormatTypeCombination =
281 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
282
283 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
284 {
285 context->handleError(Error(GL_INVALID_OPERATION));
286 return false;
287 }
288
289 // Check for pixel pack buffer related API errors
290 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
291 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
292 {
293 // ...the buffer object's data store is currently mapped.
294 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
295 return false;
296 }
297
298 // .. the data would be packed to the buffer object such that the memory writes required
299 // would exceed the data store size.
300 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
301 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
302 const gl::Extents size(width, height, 1);
303 const auto &pack = context->getGLState().getPackState();
304
305 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
306 if (endByteOrErr.isError())
307 {
308 context->handleError(endByteOrErr.getError());
309 return false;
310 }
311
312 size_t endByte = endByteOrErr.getResult();
313 if (bufSize >= 0)
314 {
315
316 if (static_cast<size_t>(bufSize) < endByte)
317 {
318 context->handleError(
319 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
320 return false;
321 }
322 }
323
324 if (pixelPackBuffer != nullptr)
325 {
326 CheckedNumeric<size_t> checkedEndByte(endByte);
327 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
328 checkedEndByte += checkedOffset;
329
330 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
331 {
332 // Overflow past the end of the buffer
333 context->handleError(
334 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
335 return false;
336 }
337 }
338
339 if (length != nullptr)
340 {
341 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
342 {
343 context->handleError(
344 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
345 return false;
346 }
347
348 *length = static_cast<GLsizei>(endByte);
349 }
350
351 return true;
352}
353
Geoff Lang740d9022016-10-07 11:20:52 -0400354bool ValidateGetRenderbufferParameterivBase(Context *context,
355 GLenum target,
356 GLenum pname,
357 GLsizei *length)
358{
359 if (length)
360 {
361 *length = 0;
362 }
363
364 if (target != GL_RENDERBUFFER)
365 {
366 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
367 return false;
368 }
369
370 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
371 if (renderbuffer == nullptr)
372 {
373 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
374 return false;
375 }
376
377 switch (pname)
378 {
379 case GL_RENDERBUFFER_WIDTH:
380 case GL_RENDERBUFFER_HEIGHT:
381 case GL_RENDERBUFFER_INTERNAL_FORMAT:
382 case GL_RENDERBUFFER_RED_SIZE:
383 case GL_RENDERBUFFER_GREEN_SIZE:
384 case GL_RENDERBUFFER_BLUE_SIZE:
385 case GL_RENDERBUFFER_ALPHA_SIZE:
386 case GL_RENDERBUFFER_DEPTH_SIZE:
387 case GL_RENDERBUFFER_STENCIL_SIZE:
388 break;
389
390 case GL_RENDERBUFFER_SAMPLES_ANGLE:
391 if (!context->getExtensions().framebufferMultisample)
392 {
393 context->handleError(
394 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
395 return false;
396 }
397 break;
398
399 default:
400 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
401 return false;
402 }
403
404 if (length)
405 {
406 *length = 1;
407 }
408 return true;
409}
410
Geoff Langd7d0ed32016-10-07 11:33:51 -0400411bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
412{
413 if (length)
414 {
415 *length = 0;
416 }
417
418 if (GetValidShader(context, shader) == nullptr)
419 {
420 return false;
421 }
422
423 switch (pname)
424 {
425 case GL_SHADER_TYPE:
426 case GL_DELETE_STATUS:
427 case GL_COMPILE_STATUS:
428 case GL_INFO_LOG_LENGTH:
429 case GL_SHADER_SOURCE_LENGTH:
430 break;
431
432 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
433 if (!context->getExtensions().translatedShaderSource)
434 {
435 context->handleError(
436 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
437 return false;
438 }
439 break;
440
441 default:
442 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
443 return false;
444 }
445
446 if (length)
447 {
448 *length = 1;
449 }
450 return true;
451}
452
Geoff Langc1984ed2016-10-07 12:41:00 -0400453bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
454{
455 if (length)
456 {
457 *length = 0;
458 }
459
460 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
461 {
462 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
463 return false;
464 }
465
466 if (context->getTargetTexture(target) == nullptr)
467 {
468 // Should only be possible for external textures
469 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
470 return false;
471 }
472
473 switch (pname)
474 {
475 case GL_TEXTURE_MAG_FILTER:
476 case GL_TEXTURE_MIN_FILTER:
477 case GL_TEXTURE_WRAP_S:
478 case GL_TEXTURE_WRAP_T:
479 break;
480
481 case GL_TEXTURE_USAGE_ANGLE:
482 if (!context->getExtensions().textureUsage)
483 {
484 context->handleError(
485 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
486 return false;
487 }
488 break;
489
490 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
491 if (!context->getExtensions().textureFilterAnisotropic)
492 {
493 context->handleError(
494 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
495 return false;
496 }
497 break;
498
499 case GL_TEXTURE_IMMUTABLE_FORMAT:
500 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
501 {
502 context->handleError(
503 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
504 return false;
505 }
506 break;
507
508 case GL_TEXTURE_WRAP_R:
509 case GL_TEXTURE_IMMUTABLE_LEVELS:
510 case GL_TEXTURE_SWIZZLE_R:
511 case GL_TEXTURE_SWIZZLE_G:
512 case GL_TEXTURE_SWIZZLE_B:
513 case GL_TEXTURE_SWIZZLE_A:
514 case GL_TEXTURE_BASE_LEVEL:
515 case GL_TEXTURE_MAX_LEVEL:
516 case GL_TEXTURE_MIN_LOD:
517 case GL_TEXTURE_MAX_LOD:
518 case GL_TEXTURE_COMPARE_MODE:
519 case GL_TEXTURE_COMPARE_FUNC:
520 if (context->getClientMajorVersion() < 3)
521 {
522 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
523 return false;
524 }
525 break;
526
Geoff Lang81c6b572016-10-19 14:07:52 -0700527 case GL_TEXTURE_SRGB_DECODE_EXT:
528 if (!context->getExtensions().textureSRGBDecode)
529 {
530 context->handleError(
531 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
532 return false;
533 }
534 break;
535
Geoff Langc1984ed2016-10-07 12:41:00 -0400536 default:
537 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
538 return false;
539 }
540
541 if (length)
542 {
543 *length = 1;
544 }
545 return true;
546}
547
548template <typename ParamType>
549bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
550{
551 switch (ConvertToGLenum(params[0]))
552 {
553 case GL_CLAMP_TO_EDGE:
554 break;
555
556 case GL_REPEAT:
557 case GL_MIRRORED_REPEAT:
558 if (isExternalTextureTarget)
559 {
560 // OES_EGL_image_external specifies this error.
561 context->handleError(Error(
562 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
563 return false;
564 }
565 break;
566
567 default:
568 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
569 return false;
570 }
571
572 return true;
573}
574
575template <typename ParamType>
576bool ValidateTextureMinFilterValue(Context *context,
577 ParamType *params,
578 bool isExternalTextureTarget)
579{
580 switch (ConvertToGLenum(params[0]))
581 {
582 case GL_NEAREST:
583 case GL_LINEAR:
584 break;
585
586 case GL_NEAREST_MIPMAP_NEAREST:
587 case GL_LINEAR_MIPMAP_NEAREST:
588 case GL_NEAREST_MIPMAP_LINEAR:
589 case GL_LINEAR_MIPMAP_LINEAR:
590 if (isExternalTextureTarget)
591 {
592 // OES_EGL_image_external specifies this error.
593 context->handleError(
594 Error(GL_INVALID_ENUM,
595 "external textures only support NEAREST and LINEAR filtering"));
596 return false;
597 }
598 break;
599
600 default:
601 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
602 return false;
603 }
604
605 return true;
606}
607
608template <typename ParamType>
609bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
610{
611 switch (ConvertToGLenum(params[0]))
612 {
613 case GL_NEAREST:
614 case GL_LINEAR:
615 break;
616
617 default:
618 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
619 return false;
620 }
621
622 return true;
623}
624
625template <typename ParamType>
626bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
627{
628 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
629 switch (ConvertToGLenum(params[0]))
630 {
631 case GL_NONE:
632 case GL_COMPARE_REF_TO_TEXTURE:
633 break;
634
635 default:
636 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
637 return false;
638 }
639
640 return true;
641}
642
643template <typename ParamType>
644bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
645{
646 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
647 switch (ConvertToGLenum(params[0]))
648 {
649 case GL_LEQUAL:
650 case GL_GEQUAL:
651 case GL_LESS:
652 case GL_GREATER:
653 case GL_EQUAL:
654 case GL_NOTEQUAL:
655 case GL_ALWAYS:
656 case GL_NEVER:
657 break;
658
659 default:
660 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
661 return false;
662 }
663
664 return true;
665}
666
667template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700668bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
669{
670 if (!context->getExtensions().textureSRGBDecode)
671 {
672 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
673 return false;
674 }
675
676 switch (ConvertToGLenum(params[0]))
677 {
678 case GL_DECODE_EXT:
679 case GL_SKIP_DECODE_EXT:
680 break;
681
682 default:
683 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
684 return false;
685 }
686
687 return true;
688}
689
690template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400691bool ValidateTexParameterBase(Context *context,
692 GLenum target,
693 GLenum pname,
694 GLsizei bufSize,
695 ParamType *params)
696{
697 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
698 {
699 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
700 return false;
701 }
702
703 if (context->getTargetTexture(target) == nullptr)
704 {
705 // Should only be possible for external textures
706 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
707 return false;
708 }
709
710 const GLsizei minBufSize = 1;
711 if (bufSize >= 0 && bufSize < minBufSize)
712 {
713 context->handleError(
714 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
715 return false;
716 }
717
718 switch (pname)
719 {
720 case GL_TEXTURE_WRAP_R:
721 case GL_TEXTURE_SWIZZLE_R:
722 case GL_TEXTURE_SWIZZLE_G:
723 case GL_TEXTURE_SWIZZLE_B:
724 case GL_TEXTURE_SWIZZLE_A:
725 case GL_TEXTURE_BASE_LEVEL:
726 case GL_TEXTURE_MAX_LEVEL:
727 case GL_TEXTURE_COMPARE_MODE:
728 case GL_TEXTURE_COMPARE_FUNC:
729 case GL_TEXTURE_MIN_LOD:
730 case GL_TEXTURE_MAX_LOD:
731 if (context->getClientMajorVersion() < 3)
732 {
733 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
734 return false;
735 }
736 if (target == GL_TEXTURE_EXTERNAL_OES &&
737 !context->getExtensions().eglImageExternalEssl3)
738 {
739 context->handleError(Error(GL_INVALID_ENUM,
740 "ES3 texture parameters are not available without "
741 "GL_OES_EGL_image_external_essl3."));
742 return false;
743 }
744 break;
745
746 default:
747 break;
748 }
749
750 switch (pname)
751 {
752 case GL_TEXTURE_WRAP_S:
753 case GL_TEXTURE_WRAP_T:
754 case GL_TEXTURE_WRAP_R:
755 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
756 {
757 return false;
758 }
759 break;
760
761 case GL_TEXTURE_MIN_FILTER:
762 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
763 {
764 return false;
765 }
766 break;
767
768 case GL_TEXTURE_MAG_FILTER:
769 if (!ValidateTextureMagFilterValue(context, params))
770 {
771 return false;
772 }
773 break;
774
775 case GL_TEXTURE_USAGE_ANGLE:
776 switch (ConvertToGLenum(params[0]))
777 {
778 case GL_NONE:
779 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
780 break;
781
782 default:
783 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
784 return false;
785 }
786 break;
787
788 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
789 if (!context->getExtensions().textureFilterAnisotropic)
790 {
791 context->handleError(
792 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
793 return false;
794 }
795
796 // we assume the parameter passed to this validation method is truncated, not rounded
797 if (params[0] < 1)
798 {
799 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
800 return false;
801 }
802 break;
803
804 case GL_TEXTURE_MIN_LOD:
805 case GL_TEXTURE_MAX_LOD:
806 // any value is permissible
807 break;
808
809 case GL_TEXTURE_COMPARE_MODE:
810 if (!ValidateTextureCompareModeValue(context, params))
811 {
812 return false;
813 }
814 break;
815
816 case GL_TEXTURE_COMPARE_FUNC:
817 if (!ValidateTextureCompareFuncValue(context, params))
818 {
819 return false;
820 }
821 break;
822
823 case GL_TEXTURE_SWIZZLE_R:
824 case GL_TEXTURE_SWIZZLE_G:
825 case GL_TEXTURE_SWIZZLE_B:
826 case GL_TEXTURE_SWIZZLE_A:
827 switch (ConvertToGLenum(params[0]))
828 {
829 case GL_RED:
830 case GL_GREEN:
831 case GL_BLUE:
832 case GL_ALPHA:
833 case GL_ZERO:
834 case GL_ONE:
835 break;
836
837 default:
838 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
839 return false;
840 }
841 break;
842
843 case GL_TEXTURE_BASE_LEVEL:
844 if (params[0] < 0)
845 {
846 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
847 return false;
848 }
849 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
850 {
851 context->handleError(
852 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
853 return false;
854 }
855 break;
856
857 case GL_TEXTURE_MAX_LEVEL:
858 if (params[0] < 0)
859 {
860 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
861 return false;
862 }
863 break;
864
Geoff Lang3b573612016-10-31 14:08:10 -0400865 case GL_DEPTH_STENCIL_TEXTURE_MODE:
866 if (context->getClientVersion() < Version(3, 1))
867 {
868 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
869 return false;
870 }
Geoff Lang9f090372016-12-02 10:20:43 -0500871 switch (ConvertToGLenum(params[0]))
872 {
873 case GL_DEPTH_COMPONENT:
874 case GL_STENCIL_INDEX:
875 break;
876
877 default:
878 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
879 return false;
880 }
Geoff Lang3b573612016-10-31 14:08:10 -0400881 break;
882
Geoff Lang81c6b572016-10-19 14:07:52 -0700883 case GL_TEXTURE_SRGB_DECODE_EXT:
884 if (!ValidateTextureSRGBDecodeValue(context, params))
885 {
886 return false;
887 }
888 break;
889
Geoff Langc1984ed2016-10-07 12:41:00 -0400890 default:
891 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
892 return false;
893 }
894
895 return true;
896}
897
898template <typename ParamType>
899bool ValidateSamplerParameterBase(Context *context,
900 GLuint sampler,
901 GLenum pname,
902 GLsizei bufSize,
903 ParamType *params)
904{
905 if (context->getClientMajorVersion() < 3)
906 {
907 context->handleError(
908 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
909 return false;
910 }
911
912 if (!context->isSampler(sampler))
913 {
914 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
915 return false;
916 }
917
918 const GLsizei minBufSize = 1;
919 if (bufSize >= 0 && bufSize < minBufSize)
920 {
921 context->handleError(
922 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
923 return false;
924 }
925
926 switch (pname)
927 {
928 case GL_TEXTURE_WRAP_S:
929 case GL_TEXTURE_WRAP_T:
930 case GL_TEXTURE_WRAP_R:
931 if (!ValidateTextureWrapModeValue(context, params, false))
932 {
933 return false;
934 }
935 break;
936
937 case GL_TEXTURE_MIN_FILTER:
938 if (!ValidateTextureMinFilterValue(context, params, false))
939 {
940 return false;
941 }
942 break;
943
944 case GL_TEXTURE_MAG_FILTER:
945 if (!ValidateTextureMagFilterValue(context, params))
946 {
947 return false;
948 }
949 break;
950
951 case GL_TEXTURE_MIN_LOD:
952 case GL_TEXTURE_MAX_LOD:
953 // any value is permissible
954 break;
955
956 case GL_TEXTURE_COMPARE_MODE:
957 if (!ValidateTextureCompareModeValue(context, params))
958 {
959 return false;
960 }
961 break;
962
963 case GL_TEXTURE_COMPARE_FUNC:
964 if (!ValidateTextureCompareFuncValue(context, params))
965 {
966 return false;
967 }
968 break;
969
Geoff Lang81c6b572016-10-19 14:07:52 -0700970 case GL_TEXTURE_SRGB_DECODE_EXT:
971 if (!ValidateTextureSRGBDecodeValue(context, params))
972 {
973 return false;
974 }
975 break;
976
Geoff Langc1984ed2016-10-07 12:41:00 -0400977 default:
978 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
979 return false;
980 }
981
982 return true;
983}
984
985bool ValidateGetSamplerParameterBase(Context *context,
986 GLuint sampler,
987 GLenum pname,
988 GLsizei *length)
989{
990 if (length)
991 {
992 *length = 0;
993 }
994
995 if (context->getClientMajorVersion() < 3)
996 {
997 context->handleError(
998 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
999 return false;
1000 }
1001
1002 if (!context->isSampler(sampler))
1003 {
1004 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
1005 return false;
1006 }
1007
1008 switch (pname)
1009 {
1010 case GL_TEXTURE_WRAP_S:
1011 case GL_TEXTURE_WRAP_T:
1012 case GL_TEXTURE_WRAP_R:
1013 case GL_TEXTURE_MIN_FILTER:
1014 case GL_TEXTURE_MAG_FILTER:
1015 case GL_TEXTURE_MIN_LOD:
1016 case GL_TEXTURE_MAX_LOD:
1017 case GL_TEXTURE_COMPARE_MODE:
1018 case GL_TEXTURE_COMPARE_FUNC:
1019 break;
1020
Geoff Lang81c6b572016-10-19 14:07:52 -07001021 case GL_TEXTURE_SRGB_DECODE_EXT:
1022 if (!context->getExtensions().textureSRGBDecode)
1023 {
1024 context->handleError(
1025 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
1026 return false;
1027 }
1028 break;
1029
Geoff Langc1984ed2016-10-07 12:41:00 -04001030 default:
1031 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1032 return false;
1033 }
1034
1035 if (length)
1036 {
1037 *length = 1;
1038 }
1039 return true;
1040}
1041
Geoff Lang0b031062016-10-13 14:30:04 -04001042bool ValidateGetVertexAttribBase(Context *context,
1043 GLuint index,
1044 GLenum pname,
1045 GLsizei *length,
1046 bool pointer,
1047 bool pureIntegerEntryPoint)
1048{
1049 if (length)
1050 {
1051 *length = 0;
1052 }
1053
1054 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1055 {
1056 context->handleError(
1057 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1058 return false;
1059 }
1060
1061 if (index >= context->getCaps().maxVertexAttributes)
1062 {
1063 context->handleError(Error(
1064 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1065 return false;
1066 }
1067
1068 if (pointer)
1069 {
1070 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1071 {
1072 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1073 return false;
1074 }
1075 }
1076 else
1077 {
1078 switch (pname)
1079 {
1080 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1081 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1082 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1083 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1084 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1085 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1086 case GL_CURRENT_VERTEX_ATTRIB:
1087 break;
1088
1089 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1090 static_assert(
1091 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1092 "ANGLE extension enums not equal to GL enums.");
1093 if (context->getClientMajorVersion() < 3 &&
1094 !context->getExtensions().instancedArrays)
1095 {
1096 context->handleError(Error(GL_INVALID_ENUM,
1097 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1098 "3.0 or GL_ANGLE_instanced_arrays."));
1099 return false;
1100 }
1101 break;
1102
1103 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1104 if (context->getClientMajorVersion() < 3)
1105 {
1106 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1107 return false;
1108 }
1109 break;
1110
1111 default:
1112 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1113 return false;
1114 }
1115 }
1116
1117 if (length)
1118 {
1119 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1120 {
1121 *length = 4;
1122 }
1123 else
1124 {
1125 *length = 1;
1126 }
1127 }
1128
1129 return true;
1130}
1131
Geoff Lang6899b872016-10-14 11:30:13 -04001132bool ValidateGetActiveUniformBlockivBase(Context *context,
1133 GLuint program,
1134 GLuint uniformBlockIndex,
1135 GLenum pname,
1136 GLsizei *length)
1137{
1138 if (length)
1139 {
1140 *length = 0;
1141 }
1142
1143 if (context->getClientMajorVersion() < 3)
1144 {
1145 context->handleError(
1146 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1147 return false;
1148 }
1149
1150 Program *programObject = GetValidProgram(context, program);
1151 if (!programObject)
1152 {
1153 return false;
1154 }
1155
1156 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1157 {
1158 context->handleError(
1159 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1160 return false;
1161 }
1162
1163 switch (pname)
1164 {
1165 case GL_UNIFORM_BLOCK_BINDING:
1166 case GL_UNIFORM_BLOCK_DATA_SIZE:
1167 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1168 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1169 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1170 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1171 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1172 break;
1173
1174 default:
1175 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1176 return false;
1177 }
1178
1179 if (length)
1180 {
1181 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1182 {
1183 const UniformBlock &uniformBlock =
1184 programObject->getUniformBlockByIndex(uniformBlockIndex);
1185 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1186 }
1187 else
1188 {
1189 *length = 1;
1190 }
1191 }
1192
1193 return true;
1194}
1195
Geoff Langebebe1c2016-10-14 12:01:31 -04001196bool ValidateGetBufferParameterBase(ValidationContext *context,
1197 GLenum target,
1198 GLenum pname,
1199 bool pointerVersion,
1200 GLsizei *numParams)
1201{
1202 if (numParams)
1203 {
1204 *numParams = 0;
1205 }
1206
1207 if (!ValidBufferTarget(context, target))
1208 {
1209 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1210 return false;
1211 }
1212
1213 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1214 if (!buffer)
1215 {
1216 // A null buffer means that "0" is bound to the requested buffer target
1217 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1218 return false;
1219 }
1220
1221 const Extensions &extensions = context->getExtensions();
1222
1223 switch (pname)
1224 {
1225 case GL_BUFFER_USAGE:
1226 case GL_BUFFER_SIZE:
1227 break;
1228
1229 case GL_BUFFER_ACCESS_OES:
1230 if (!extensions.mapBuffer)
1231 {
1232 context->handleError(
Jamie Madillcc6ac252017-01-25 12:57:21 -08001233 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001234 return false;
1235 }
1236 break;
1237
1238 case GL_BUFFER_MAPPED:
1239 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1240 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1241 !extensions.mapBufferRange)
1242 {
1243 context->handleError(Error(
1244 GL_INVALID_ENUM,
Jamie Madillcc6ac252017-01-25 12:57:21 -08001245 "pname requires OpenGL ES 3.0, GL_OES_mapbuffer or GL_EXT_map_buffer_range."));
Geoff Langebebe1c2016-10-14 12:01:31 -04001246 return false;
1247 }
1248 break;
1249
1250 case GL_BUFFER_MAP_POINTER:
1251 if (!pointerVersion)
1252 {
1253 context->handleError(
1254 Error(GL_INVALID_ENUM,
1255 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1256 return false;
1257 }
1258 break;
1259
1260 case GL_BUFFER_ACCESS_FLAGS:
1261 case GL_BUFFER_MAP_OFFSET:
1262 case GL_BUFFER_MAP_LENGTH:
1263 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1264 {
1265 context->handleError(Error(
1266 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1267 return false;
1268 }
1269 break;
1270
1271 default:
1272 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1273 return false;
1274 }
1275
1276 // All buffer parameter queries return one value.
1277 if (numParams)
1278 {
1279 *numParams = 1;
1280 }
1281
1282 return true;
1283}
1284
Geoff Lang0a9661f2016-10-20 10:59:20 -07001285bool ValidateGetInternalFormativBase(Context *context,
1286 GLenum target,
1287 GLenum internalformat,
1288 GLenum pname,
1289 GLsizei bufSize,
1290 GLsizei *numParams)
1291{
1292 if (numParams)
1293 {
1294 *numParams = 0;
1295 }
1296
1297 if (context->getClientMajorVersion() < 3)
1298 {
1299 context->handleError(
1300 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1301 return false;
1302 }
1303
1304 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1305 if (!formatCaps.renderable)
1306 {
1307 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1308 return false;
1309 }
1310
1311 switch (target)
1312 {
1313 case GL_RENDERBUFFER:
1314 break;
1315
JiangYizhoubddc46b2016-12-09 09:50:51 +08001316 case GL_TEXTURE_2D_MULTISAMPLE:
1317 if (context->getClientVersion() < ES_3_1)
1318 {
1319 context->handleError(
1320 Error(GL_INVALID_OPERATION, "Texture target requires at least OpenGL ES 3.1."));
1321 return false;
1322 }
1323 break;
1324
Geoff Lang0a9661f2016-10-20 10:59:20 -07001325 default:
1326 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1327 return false;
1328 }
1329
1330 if (bufSize < 0)
1331 {
1332 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1333 return false;
1334 }
1335
1336 GLsizei maxWriteParams = 0;
1337 switch (pname)
1338 {
1339 case GL_NUM_SAMPLE_COUNTS:
1340 maxWriteParams = 1;
1341 break;
1342
1343 case GL_SAMPLES:
1344 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1345 break;
1346
1347 default:
1348 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1349 return false;
1350 }
1351
1352 if (numParams)
1353 {
1354 // glGetInternalFormativ will not overflow bufSize
1355 *numParams = std::min(bufSize, maxWriteParams);
1356 }
1357
1358 return true;
1359}
1360
Geoff Langf41a7152016-09-19 15:11:17 -04001361} // anonymous namespace
1362
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001363bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001364{
Jamie Madilld7460c72014-01-21 16:38:14 -05001365 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001366 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001367 case GL_TEXTURE_2D:
1368 case GL_TEXTURE_CUBE_MAP:
1369 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001370
He Yunchaoced53ae2016-11-29 15:00:51 +08001371 case GL_TEXTURE_3D:
1372 case GL_TEXTURE_2D_ARRAY:
1373 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001374
He Yunchaoced53ae2016-11-29 15:00:51 +08001375 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001376 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001377
He Yunchaoced53ae2016-11-29 15:00:51 +08001378 default:
1379 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001380 }
Jamie Madill35d15012013-10-07 10:46:37 -04001381}
1382
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001383bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1384{
1385 switch (target)
1386 {
1387 case GL_TEXTURE_2D:
1388 case GL_TEXTURE_CUBE_MAP:
1389 return true;
1390
1391 default:
1392 return false;
1393 }
1394}
1395
1396bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1397{
1398 switch (target)
1399 {
1400 case GL_TEXTURE_3D:
1401 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001402 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001403
1404 default:
1405 return false;
1406 }
1407}
1408
Ian Ewellbda75592016-04-18 17:25:54 -04001409// Most texture GL calls are not compatible with external textures, so we have a separate validation
1410// function for use in the GL calls that do
1411bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1412{
1413 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1414 (context->getExtensions().eglImageExternal ||
1415 context->getExtensions().eglStreamConsumerExternal);
1416}
1417
Shannon Woods4dfed832014-03-17 20:03:39 -04001418// This function differs from ValidTextureTarget in that the target must be
1419// usable as the destination of a 2D operation-- so a cube face is valid, but
1420// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001421// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001422bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001423{
1424 switch (target)
1425 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001426 case GL_TEXTURE_2D:
1427 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1428 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1429 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1430 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1431 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1432 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1433 return true;
1434 default:
1435 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001436 }
1437}
1438
1439bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1440{
1441 switch (target)
1442 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001443 case GL_TEXTURE_3D:
1444 case GL_TEXTURE_2D_ARRAY:
1445 return true;
1446 default:
1447 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001448 }
1449}
1450
He Yunchao11b038b2016-11-22 21:24:04 +08001451bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1452{
1453 switch (target)
1454 {
1455 case GL_TEXTURE_2D:
1456 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1457 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1458 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1459 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1460 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1461 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1462 case GL_TEXTURE_3D:
1463 case GL_TEXTURE_2D_ARRAY:
1464 case GL_TEXTURE_2D_MULTISAMPLE:
1465 return true;
1466 default:
1467 return false;
1468 }
1469}
1470
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001471bool ValidFramebufferTarget(GLenum target)
1472{
He Yunchaoced53ae2016-11-29 15:00:51 +08001473 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1474 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001475 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001476
1477 switch (target)
1478 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001479 case GL_FRAMEBUFFER:
1480 return true;
1481 case GL_READ_FRAMEBUFFER:
1482 return true;
1483 case GL_DRAW_FRAMEBUFFER:
1484 return true;
1485 default:
1486 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001487 }
1488}
1489
Jamie Madill29639852016-09-02 15:00:09 -04001490bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001491{
1492 switch (target)
1493 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001494 case GL_ARRAY_BUFFER:
1495 case GL_ELEMENT_ARRAY_BUFFER:
1496 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001497
He Yunchaoced53ae2016-11-29 15:00:51 +08001498 case GL_PIXEL_PACK_BUFFER:
1499 case GL_PIXEL_UNPACK_BUFFER:
1500 return (context->getExtensions().pixelBufferObject ||
1501 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001502
He Yunchaoced53ae2016-11-29 15:00:51 +08001503 case GL_COPY_READ_BUFFER:
1504 case GL_COPY_WRITE_BUFFER:
1505 case GL_TRANSFORM_FEEDBACK_BUFFER:
1506 case GL_UNIFORM_BUFFER:
1507 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001508
He Yunchaoced53ae2016-11-29 15:00:51 +08001509 case GL_ATOMIC_COUNTER_BUFFER:
1510 case GL_SHADER_STORAGE_BUFFER:
1511 case GL_DRAW_INDIRECT_BUFFER:
1512 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001513 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001514
He Yunchaoced53ae2016-11-29 15:00:51 +08001515 default:
1516 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001517 }
1518}
1519
Jamie Madillc29968b2016-01-20 11:17:23 -05001520bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001521{
Jamie Madillc29968b2016-01-20 11:17:23 -05001522 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001523 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001524 switch (target)
1525 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001526 case GL_TEXTURE_2D:
1527 maxDimension = caps.max2DTextureSize;
1528 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001529 case GL_TEXTURE_CUBE_MAP:
1530 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1531 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1532 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1533 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1534 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1535 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1536 maxDimension = caps.maxCubeMapTextureSize;
1537 break;
1538 case GL_TEXTURE_3D:
1539 maxDimension = caps.max3DTextureSize;
1540 break;
1541 case GL_TEXTURE_2D_ARRAY:
1542 maxDimension = caps.max2DTextureSize;
1543 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001544 case GL_TEXTURE_2D_MULTISAMPLE:
1545 maxDimension = caps.max2DTextureSize;
1546 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001547 default:
1548 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001549 }
1550
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001551 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001552}
1553
Geoff Langcc507aa2016-12-12 10:09:52 -05001554bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001555 GLenum target,
1556 GLint level,
1557 GLsizei width,
1558 GLsizei height,
1559 GLsizei depth,
1560 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001561{
1562 if (level < 0 || width < 0 || height < 0 || depth < 0)
1563 {
1564 return false;
1565 }
1566
Austin Kinross08528e12015-10-07 16:24:40 -07001567 // TexSubImage parameters can be NPOT without textureNPOT extension,
1568 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001569 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001570 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001571 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001572 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001573 {
1574 return false;
1575 }
1576
1577 if (!ValidMipLevel(context, target, level))
1578 {
1579 return false;
1580 }
1581
1582 return true;
1583}
1584
Geoff Lang0d8b7242015-09-09 14:56:53 -04001585bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1586{
1587 // List of compressed format that require that the texture size is smaller than or a multiple of
1588 // the compressed block size.
1589 switch (internalFormat)
1590 {
1591 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1592 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1593 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1594 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001595 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001596 return true;
1597
1598 default:
1599 return false;
1600 }
1601}
1602
Jamie Madillc29968b2016-01-20 11:17:23 -05001603bool ValidCompressedImageSize(const ValidationContext *context,
1604 GLenum internalFormat,
1605 GLsizei width,
1606 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001607{
Geoff Lang5d601382014-07-22 15:14:06 -04001608 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1609 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001610 {
1611 return false;
1612 }
1613
Geoff Lang0d8b7242015-09-09 14:56:53 -04001614 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001615 {
1616 return false;
1617 }
1618
Geoff Lang0d8b7242015-09-09 14:56:53 -04001619 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1620 {
1621 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1622 width % formatInfo.compressedBlockWidth != 0) ||
1623 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1624 height % formatInfo.compressedBlockHeight != 0))
1625 {
1626 return false;
1627 }
1628 }
1629
Geoff Langd4f180b2013-09-24 13:57:44 -04001630 return true;
1631}
1632
Geoff Langff5b2d52016-09-07 11:32:23 -04001633bool ValidImageDataSize(ValidationContext *context,
1634 GLenum textureTarget,
1635 GLsizei width,
1636 GLsizei height,
1637 GLsizei depth,
1638 GLenum internalFormat,
1639 GLenum type,
1640 const GLvoid *pixels,
1641 GLsizei imageSize)
1642{
1643 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1644 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1645 {
1646 // Checks are not required
1647 return true;
1648 }
1649
1650 // ...the data would be unpacked from the buffer object such that the memory reads required
1651 // would exceed the data store size.
1652 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1653 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1654 const gl::Extents size(width, height, depth);
1655 const auto &unpack = context->getGLState().getUnpackState();
1656
1657 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1658 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1659 if (endByteOrErr.isError())
1660 {
1661 context->handleError(endByteOrErr.getError());
1662 return false;
1663 }
1664
1665 GLuint endByte = endByteOrErr.getResult();
1666
1667 if (pixelUnpackBuffer)
1668 {
1669 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1670 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1671 checkedEndByte += checkedOffset;
1672
1673 if (!checkedEndByte.IsValid() ||
1674 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1675 {
1676 // Overflow past the end of the buffer
1677 context->handleError(Error(GL_INVALID_OPERATION));
1678 return false;
1679 }
1680 }
1681 else
1682 {
1683 ASSERT(imageSize >= 0);
1684 if (pixels == nullptr && imageSize != 0)
1685 {
1686 context->handleError(
1687 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001688 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001689 }
1690
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001691 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001692 {
1693 context->handleError(
1694 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1695 return false;
1696 }
1697 }
1698
1699 return true;
1700}
1701
Geoff Lang37dde692014-01-31 16:34:54 -05001702bool ValidQueryType(const Context *context, GLenum queryType)
1703{
He Yunchaoced53ae2016-11-29 15:00:51 +08001704 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1705 "GL extension enums not equal.");
1706 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1707 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001708
1709 switch (queryType)
1710 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001711 case GL_ANY_SAMPLES_PASSED:
1712 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1713 return true;
1714 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1715 return (context->getClientMajorVersion() >= 3);
1716 case GL_TIME_ELAPSED_EXT:
1717 return context->getExtensions().disjointTimerQuery;
1718 case GL_COMMANDS_COMPLETED_CHROMIUM:
1719 return context->getExtensions().syncQuery;
1720 default:
1721 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001722 }
1723}
1724
Jamie Madillef300b12016-10-07 15:12:09 -04001725Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001726{
He Yunchaoced53ae2016-11-29 15:00:51 +08001727 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1728 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1729 // or program object and INVALID_OPERATION if the provided name identifies an object
1730 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001731
Dian Xiang769769a2015-09-09 15:20:08 -07001732 Program *validProgram = context->getProgram(id);
1733
1734 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001735 {
Dian Xiang769769a2015-09-09 15:20:08 -07001736 if (context->getShader(id))
1737 {
Jamie Madill437fa652016-05-03 15:13:24 -04001738 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001739 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1740 }
1741 else
1742 {
Jamie Madill437fa652016-05-03 15:13:24 -04001743 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001744 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001745 }
Dian Xiang769769a2015-09-09 15:20:08 -07001746
1747 return validProgram;
1748}
1749
Jamie Madillef300b12016-10-07 15:12:09 -04001750Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001751{
1752 // See ValidProgram for spec details.
1753
1754 Shader *validShader = context->getShader(id);
1755
1756 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001757 {
Dian Xiang769769a2015-09-09 15:20:08 -07001758 if (context->getProgram(id))
1759 {
Jamie Madill437fa652016-05-03 15:13:24 -04001760 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001761 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1762 }
1763 else
1764 {
Jamie Madill437fa652016-05-03 15:13:24 -04001765 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001766 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001767 }
Dian Xiang769769a2015-09-09 15:20:08 -07001768
1769 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001770}
1771
Geoff Langb1196682014-07-23 13:47:29 -04001772bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001773{
1774 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1775 {
1776 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1777
Geoff Langaae65a42014-05-26 12:43:44 -04001778 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001779 {
Jamie Madill437fa652016-05-03 15:13:24 -04001780 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001781 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001782 }
1783 }
1784 else
1785 {
1786 switch (attachment)
1787 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001788 case GL_DEPTH_ATTACHMENT:
1789 case GL_STENCIL_ATTACHMENT:
1790 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001791
He Yunchaoced53ae2016-11-29 15:00:51 +08001792 case GL_DEPTH_STENCIL_ATTACHMENT:
1793 if (!context->getExtensions().webglCompatibility &&
1794 context->getClientMajorVersion() < 3)
1795 {
1796 context->handleError(Error(GL_INVALID_ENUM));
1797 return false;
1798 }
1799 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001800
He Yunchaoced53ae2016-11-29 15:00:51 +08001801 default:
1802 context->handleError(Error(GL_INVALID_ENUM));
1803 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001804 }
1805 }
1806
1807 return true;
1808}
1809
He Yunchaoced53ae2016-11-29 15:00:51 +08001810bool ValidateRenderbufferStorageParametersBase(gl::Context *context,
1811 GLenum target,
1812 GLsizei samples,
1813 GLenum internalformat,
1814 GLsizei width,
1815 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001816{
1817 switch (target)
1818 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001819 case GL_RENDERBUFFER:
1820 break;
1821 default:
1822 context->handleError(Error(GL_INVALID_ENUM));
1823 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001824 }
1825
1826 if (width < 0 || height < 0 || samples < 0)
1827 {
Jamie Madill437fa652016-05-03 15:13:24 -04001828 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001829 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001830 }
1831
Geoff Langd87878e2014-09-19 15:42:59 -04001832 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1833 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001834 {
Jamie Madill437fa652016-05-03 15:13:24 -04001835 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001836 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001837 }
1838
1839 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1840 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
Corentin Walleze0902642014-11-04 12:32:15 -08001841 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001842 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001843 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001844 {
Jamie Madill437fa652016-05-03 15:13:24 -04001845 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001846 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001847 }
1848
Geoff Langaae65a42014-05-26 12:43:44 -04001849 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001850 {
Jamie Madill437fa652016-05-03 15:13:24 -04001851 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001852 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001853 }
1854
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001855 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001856 if (handle == 0)
1857 {
Jamie Madill437fa652016-05-03 15:13:24 -04001858 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001859 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001860 }
1861
1862 return true;
1863}
1864
He Yunchaoced53ae2016-11-29 15:00:51 +08001865bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context,
1866 GLenum target,
1867 GLsizei samples,
1868 GLenum internalformat,
1869 GLsizei width,
1870 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -08001871{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001872 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001873
1874 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001875 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001876 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001877 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001878 {
Jamie Madill437fa652016-05-03 15:13:24 -04001879 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001880 return false;
1881 }
1882
1883 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1884 // the specified storage. This is different than ES 3.0 in which a sample number higher
1885 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001886 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001887 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001888 {
Geoff Langa4903b72015-03-02 16:02:48 -08001889 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1890 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1891 {
Jamie Madill437fa652016-05-03 15:13:24 -04001892 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001893 return false;
1894 }
Corentin Walleze0902642014-11-04 12:32:15 -08001895 }
1896
He Yunchaoced53ae2016-11-29 15:00:51 +08001897 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
1898 width, height);
Corentin Walleze0902642014-11-04 12:32:15 -08001899}
1900
He Yunchaoced53ae2016-11-29 15:00:51 +08001901bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1902 GLenum target,
1903 GLenum attachment,
1904 GLenum renderbuffertarget,
1905 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001906{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001907 if (!ValidFramebufferTarget(target))
1908 {
Jamie Madill437fa652016-05-03 15:13:24 -04001909 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001910 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001911 }
1912
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001913 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001914
Jamie Madill84115c92015-04-23 15:00:07 -04001915 ASSERT(framebuffer);
1916 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001917 {
Jamie Madill437fa652016-05-03 15:13:24 -04001918 context->handleError(
1919 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001920 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001921 }
1922
Jamie Madillb4472272014-07-03 10:38:55 -04001923 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001924 {
Jamie Madillb4472272014-07-03 10:38:55 -04001925 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001926 }
1927
Jamie Madillab9d82c2014-01-21 16:38:14 -05001928 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1929 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1930 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1931 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1932 if (renderbuffer != 0)
1933 {
1934 if (!context->getRenderbuffer(renderbuffer))
1935 {
Jamie Madill437fa652016-05-03 15:13:24 -04001936 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001937 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001938 }
1939 }
1940
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001941 return true;
1942}
1943
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001944bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001945 GLint srcX0,
1946 GLint srcY0,
1947 GLint srcX1,
1948 GLint srcY1,
1949 GLint dstX0,
1950 GLint dstY0,
1951 GLint dstX1,
1952 GLint dstY1,
1953 GLbitfield mask,
1954 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001955{
1956 switch (filter)
1957 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001958 case GL_NEAREST:
1959 break;
1960 case GL_LINEAR:
1961 break;
1962 default:
1963 context->handleError(Error(GL_INVALID_ENUM));
1964 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001965 }
1966
1967 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1968 {
Jamie Madill437fa652016-05-03 15:13:24 -04001969 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001970 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001971 }
1972
1973 if (mask == 0)
1974 {
1975 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1976 // buffers are copied.
1977 return false;
1978 }
1979
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001980 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1981 // color buffer, leaving only nearest being unfiltered from above
1982 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1983 {
Jamie Madill437fa652016-05-03 15:13:24 -04001984 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001985 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001986 }
1987
Jamie Madill51f40ec2016-06-15 14:06:00 -04001988 const auto &glState = context->getGLState();
1989 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1990 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001991
1992 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001993 {
Jamie Madill437fa652016-05-03 15:13:24 -04001994 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001995 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001996 }
1997
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001998 if (readFramebuffer->id() == drawFramebuffer->id())
1999 {
2000 context->handleError(Error(GL_INVALID_OPERATION));
2001 return false;
2002 }
2003
Jamie Madill51f40ec2016-06-15 14:06:00 -04002004 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002005 {
Jamie Madill437fa652016-05-03 15:13:24 -04002006 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002007 return false;
2008 }
2009
Jamie Madill51f40ec2016-06-15 14:06:00 -04002010 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002011 {
Jamie Madill437fa652016-05-03 15:13:24 -04002012 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002013 return false;
2014 }
2015
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002016 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002017 {
Jamie Madill437fa652016-05-03 15:13:24 -04002018 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002019 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002020 }
2021
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002022 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2023
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002024 if (mask & GL_COLOR_BUFFER_BIT)
2025 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002026 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002027 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002028
He Yunchao66a41a22016-12-15 16:45:05 +08002029 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002030 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002031 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002032
Geoff Langa15472a2015-08-11 11:48:03 -04002033 for (size_t drawbufferIdx = 0;
2034 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002035 {
Geoff Langa15472a2015-08-11 11:48:03 -04002036 const FramebufferAttachment *attachment =
2037 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2038 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002039 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002040 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002041
Geoff Langb2f3d052013-08-13 12:49:27 -04002042 // The GL ES 3.0.2 spec (pg 193) states that:
2043 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002044 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2045 // as well
2046 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2047 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002048 // Changes with EXT_color_buffer_float:
2049 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002050 GLenum readComponentType = readFormat.info->componentType;
2051 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002052 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002053 readComponentType == GL_SIGNED_NORMALIZED);
2054 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2055 drawComponentType == GL_SIGNED_NORMALIZED);
2056
2057 if (extensions.colorBufferFloat)
2058 {
2059 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2060 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2061
2062 if (readFixedOrFloat != drawFixedOrFloat)
2063 {
Jamie Madill437fa652016-05-03 15:13:24 -04002064 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002065 "If the read buffer contains fixed-point or "
2066 "floating-point values, the draw buffer "
2067 "must as well."));
2068 return false;
2069 }
2070 }
2071 else if (readFixedPoint != drawFixedPoint)
2072 {
Jamie Madill437fa652016-05-03 15:13:24 -04002073 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002074 "If the read buffer contains fixed-point "
2075 "values, the draw buffer must as well."));
2076 return false;
2077 }
2078
2079 if (readComponentType == GL_UNSIGNED_INT &&
2080 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002081 {
Jamie Madill437fa652016-05-03 15:13:24 -04002082 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002083 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002084 }
2085
Jamie Madill6163c752015-12-07 16:32:59 -05002086 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002087 {
Jamie Madill437fa652016-05-03 15:13:24 -04002088 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002089 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002090 }
2091
Jamie Madilla3944d42016-07-22 22:13:26 -04002092 if (readColorBuffer->getSamples() > 0 &&
2093 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002094 {
Jamie Madill437fa652016-05-03 15:13:24 -04002095 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002096 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002097 }
2098 }
2099 }
2100
Jamie Madilla3944d42016-07-22 22:13:26 -04002101 if ((readFormat.info->componentType == GL_INT ||
2102 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2103 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002104 {
Jamie Madill437fa652016-05-03 15:13:24 -04002105 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002106 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002107 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002108 }
He Yunchao66a41a22016-12-15 16:45:05 +08002109 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2110 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2111 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2112 // situation is an application error that would lead to a crash in ANGLE.
2113 else if (drawFramebuffer->hasEnabledDrawBuffer())
2114 {
2115 context->handleError(Error(
2116 GL_INVALID_OPERATION,
2117 "Attempt to read from a missing color attachment of a complete framebuffer."));
2118 return false;
2119 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002120 }
2121
He Yunchaoced53ae2016-11-29 15:00:51 +08002122 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002123 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2124 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002125 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002126 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002127 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002128 const gl::FramebufferAttachment *readBuffer =
2129 readFramebuffer->getAttachment(attachments[i]);
2130 const gl::FramebufferAttachment *drawBuffer =
2131 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002132
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002133 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002134 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002135 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002136 {
Jamie Madill437fa652016-05-03 15:13:24 -04002137 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002138 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002139 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002140
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002141 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002142 {
Jamie Madill437fa652016-05-03 15:13:24 -04002143 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002144 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002145 }
2146 }
He Yunchao66a41a22016-12-15 16:45:05 +08002147 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2148 else if (drawBuffer)
2149 {
2150 context->handleError(Error(GL_INVALID_OPERATION,
2151 "Attempt to read from a missing depth/stencil "
2152 "attachment of a complete framebuffer."));
2153 return false;
2154 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002155 }
2156 }
2157
2158 return true;
2159}
2160
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002161bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002162 GLint x,
2163 GLint y,
2164 GLsizei width,
2165 GLsizei height,
2166 GLenum format,
2167 GLenum type,
2168 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002169{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002170 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2171}
2172
2173bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2174 GLint x,
2175 GLint y,
2176 GLsizei width,
2177 GLsizei height,
2178 GLenum format,
2179 GLenum type,
2180 GLsizei bufSize,
2181 GLsizei *length,
2182 GLvoid *pixels)
2183{
2184 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002185 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002186 return false;
2187 }
2188
Geoff Lang62fce5b2016-09-30 10:46:35 -04002189 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2190 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002191 {
Geoff Langb1196682014-07-23 13:47:29 -04002192 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002193 }
2194
Geoff Lang62fce5b2016-09-30 10:46:35 -04002195 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002196 {
Geoff Langb1196682014-07-23 13:47:29 -04002197 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002198 }
2199
Jamie Madillc29968b2016-01-20 11:17:23 -05002200 return true;
2201}
2202
2203bool ValidateReadnPixelsEXT(Context *context,
2204 GLint x,
2205 GLint y,
2206 GLsizei width,
2207 GLsizei height,
2208 GLenum format,
2209 GLenum type,
2210 GLsizei bufSize,
2211 GLvoid *pixels)
2212{
2213 if (bufSize < 0)
2214 {
Jamie Madill437fa652016-05-03 15:13:24 -04002215 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002216 return false;
2217 }
2218
Geoff Lang62fce5b2016-09-30 10:46:35 -04002219 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2220 pixels);
2221}
Jamie Madill26e91952014-03-05 15:01:27 -05002222
Geoff Lang62fce5b2016-09-30 10:46:35 -04002223bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2224 GLint x,
2225 GLint y,
2226 GLsizei width,
2227 GLsizei height,
2228 GLenum format,
2229 GLenum type,
2230 GLsizei bufSize,
2231 GLsizei *length,
2232 GLvoid *data)
2233{
2234 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002235 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002236 return false;
2237 }
2238
Geoff Lang62fce5b2016-09-30 10:46:35 -04002239 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002240 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002241 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002242 }
2243
Geoff Lang62fce5b2016-09-30 10:46:35 -04002244 if (!ValidateRobustBufferSize(context, bufSize, *length))
2245 {
2246 return false;
2247 }
2248
2249 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002250}
2251
Olli Etuaho41997e72016-03-10 13:38:39 +02002252bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002253{
2254 if (!context->getExtensions().occlusionQueryBoolean &&
2255 !context->getExtensions().disjointTimerQuery)
2256 {
Jamie Madill437fa652016-05-03 15:13:24 -04002257 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002258 return false;
2259 }
2260
Olli Etuaho41997e72016-03-10 13:38:39 +02002261 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002262}
2263
Olli Etuaho41997e72016-03-10 13:38:39 +02002264bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002265{
2266 if (!context->getExtensions().occlusionQueryBoolean &&
2267 !context->getExtensions().disjointTimerQuery)
2268 {
Jamie Madill437fa652016-05-03 15:13:24 -04002269 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002270 return false;
2271 }
2272
Olli Etuaho41997e72016-03-10 13:38:39 +02002273 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002274}
2275
2276bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002277{
2278 if (!ValidQueryType(context, target))
2279 {
Jamie Madill437fa652016-05-03 15:13:24 -04002280 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002281 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002282 }
2283
2284 if (id == 0)
2285 {
Jamie Madill437fa652016-05-03 15:13:24 -04002286 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002287 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002288 }
2289
2290 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2291 // of zero, if the active query object name for <target> is non-zero (for the
2292 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2293 // the active query for either target is non-zero), if <id> is the name of an
2294 // existing query object whose type does not match <target>, or if <id> is the
2295 // active query object name for any query type, the error INVALID_OPERATION is
2296 // generated.
2297
2298 // Ensure no other queries are active
2299 // NOTE: If other queries than occlusion are supported, we will need to check
2300 // separately that:
2301 // a) The query ID passed is not the current active query for any target/type
2302 // b) There are no active queries for the requested target (and in the case
2303 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2304 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002305
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002306 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002307 {
Jamie Madill437fa652016-05-03 15:13:24 -04002308 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002309 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002310 }
2311
2312 Query *queryObject = context->getQuery(id, true, target);
2313
2314 // check that name was obtained with glGenQueries
2315 if (!queryObject)
2316 {
Jamie Madill437fa652016-05-03 15:13:24 -04002317 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002318 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002319 }
2320
2321 // check for type mismatch
2322 if (queryObject->getType() != target)
2323 {
Jamie Madill437fa652016-05-03 15:13:24 -04002324 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002325 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002326 }
2327
2328 return true;
2329}
2330
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002331bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2332{
2333 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002334 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002335 {
Jamie Madill437fa652016-05-03 15:13:24 -04002336 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002337 return false;
2338 }
2339
2340 return ValidateBeginQueryBase(context, target, id);
2341}
2342
2343bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002344{
2345 if (!ValidQueryType(context, target))
2346 {
Jamie Madill437fa652016-05-03 15:13:24 -04002347 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002348 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002349 }
2350
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002351 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002352
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002353 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002354 {
Jamie Madill437fa652016-05-03 15:13:24 -04002355 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002356 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002357 }
2358
Jamie Madill45c785d2014-05-13 14:09:34 -04002359 return true;
2360}
2361
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002362bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2363{
2364 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002365 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002366 {
Jamie Madill437fa652016-05-03 15:13:24 -04002367 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002368 return false;
2369 }
2370
2371 return ValidateEndQueryBase(context, target);
2372}
2373
2374bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2375{
2376 if (!context->getExtensions().disjointTimerQuery)
2377 {
Jamie Madill437fa652016-05-03 15:13:24 -04002378 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002379 return false;
2380 }
2381
2382 if (target != GL_TIMESTAMP_EXT)
2383 {
Jamie Madill437fa652016-05-03 15:13:24 -04002384 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002385 return false;
2386 }
2387
2388 Query *queryObject = context->getQuery(id, true, target);
2389 if (queryObject == nullptr)
2390 {
Jamie Madill437fa652016-05-03 15:13:24 -04002391 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002392 return false;
2393 }
2394
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002395 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002396 {
Jamie Madill437fa652016-05-03 15:13:24 -04002397 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002398 return false;
2399 }
2400
2401 return true;
2402}
2403
Geoff Lang2186c382016-10-14 10:54:54 -04002404bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002405{
Geoff Lang2186c382016-10-14 10:54:54 -04002406 if (numParams)
2407 {
2408 *numParams = 0;
2409 }
2410
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002411 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2412 {
Jamie Madill437fa652016-05-03 15:13:24 -04002413 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002414 return false;
2415 }
2416
2417 switch (pname)
2418 {
2419 case GL_CURRENT_QUERY_EXT:
2420 if (target == GL_TIMESTAMP_EXT)
2421 {
Jamie Madill437fa652016-05-03 15:13:24 -04002422 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002423 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2424 return false;
2425 }
2426 break;
2427 case GL_QUERY_COUNTER_BITS_EXT:
2428 if (!context->getExtensions().disjointTimerQuery ||
2429 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2430 {
Jamie Madill437fa652016-05-03 15:13:24 -04002431 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002432 return false;
2433 }
2434 break;
2435 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002436 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002437 return false;
2438 }
2439
Geoff Lang2186c382016-10-14 10:54:54 -04002440 if (numParams)
2441 {
2442 // All queries return only one value
2443 *numParams = 1;
2444 }
2445
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002446 return true;
2447}
2448
2449bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2450{
2451 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002452 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002453 {
Jamie Madill437fa652016-05-03 15:13:24 -04002454 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002455 return false;
2456 }
2457
Geoff Lang2186c382016-10-14 10:54:54 -04002458 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002459}
2460
Geoff Lang2186c382016-10-14 10:54:54 -04002461bool ValidateGetQueryivRobustANGLE(Context *context,
2462 GLenum target,
2463 GLenum pname,
2464 GLsizei bufSize,
2465 GLsizei *length,
2466 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002467{
Geoff Lang2186c382016-10-14 10:54:54 -04002468 if (!ValidateRobustEntryPoint(context, bufSize))
2469 {
2470 return false;
2471 }
2472
2473 if (!ValidateGetQueryivBase(context, target, pname, length))
2474 {
2475 return false;
2476 }
2477
2478 if (!ValidateRobustBufferSize(context, bufSize, *length))
2479 {
2480 return false;
2481 }
2482
2483 return true;
2484}
2485
2486bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2487{
2488 if (numParams)
2489 {
2490 *numParams = 0;
2491 }
2492
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002493 Query *queryObject = context->getQuery(id, false, GL_NONE);
2494
2495 if (!queryObject)
2496 {
Jamie Madill437fa652016-05-03 15:13:24 -04002497 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002498 return false;
2499 }
2500
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002501 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002502 {
Jamie Madill437fa652016-05-03 15:13:24 -04002503 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002504 return false;
2505 }
2506
2507 switch (pname)
2508 {
2509 case GL_QUERY_RESULT_EXT:
2510 case GL_QUERY_RESULT_AVAILABLE_EXT:
2511 break;
2512
2513 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002514 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002515 return false;
2516 }
2517
Geoff Lang2186c382016-10-14 10:54:54 -04002518 if (numParams)
2519 {
2520 *numParams = 1;
2521 }
2522
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002523 return true;
2524}
2525
2526bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2527{
2528 if (!context->getExtensions().disjointTimerQuery)
2529 {
Jamie Madill437fa652016-05-03 15:13:24 -04002530 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002531 return false;
2532 }
Geoff Lang2186c382016-10-14 10:54:54 -04002533 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2534}
2535
2536bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2537 GLuint id,
2538 GLenum pname,
2539 GLsizei bufSize,
2540 GLsizei *length,
2541 GLint *params)
2542{
2543 if (!context->getExtensions().disjointTimerQuery)
2544 {
2545 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2546 return false;
2547 }
2548
2549 if (!ValidateRobustEntryPoint(context, bufSize))
2550 {
2551 return false;
2552 }
2553
2554 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2555 {
2556 return false;
2557 }
2558
2559 if (!ValidateRobustBufferSize(context, bufSize, *length))
2560 {
2561 return false;
2562 }
2563
2564 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002565}
2566
2567bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2568{
2569 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002570 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002571 {
Jamie Madill437fa652016-05-03 15:13:24 -04002572 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002573 return false;
2574 }
Geoff Lang2186c382016-10-14 10:54:54 -04002575 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2576}
2577
2578bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2579 GLuint id,
2580 GLenum pname,
2581 GLsizei bufSize,
2582 GLsizei *length,
2583 GLuint *params)
2584{
2585 if (!context->getExtensions().disjointTimerQuery &&
2586 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2587 {
2588 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2589 return false;
2590 }
2591
2592 if (!ValidateRobustEntryPoint(context, bufSize))
2593 {
2594 return false;
2595 }
2596
2597 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2598 {
2599 return false;
2600 }
2601
2602 if (!ValidateRobustBufferSize(context, bufSize, *length))
2603 {
2604 return false;
2605 }
2606
2607 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002608}
2609
2610bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2611{
2612 if (!context->getExtensions().disjointTimerQuery)
2613 {
Jamie Madill437fa652016-05-03 15:13:24 -04002614 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002615 return false;
2616 }
Geoff Lang2186c382016-10-14 10:54:54 -04002617 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2618}
2619
2620bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2621 GLuint id,
2622 GLenum pname,
2623 GLsizei bufSize,
2624 GLsizei *length,
2625 GLint64 *params)
2626{
2627 if (!context->getExtensions().disjointTimerQuery)
2628 {
2629 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2630 return false;
2631 }
2632
2633 if (!ValidateRobustEntryPoint(context, bufSize))
2634 {
2635 return false;
2636 }
2637
2638 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2639 {
2640 return false;
2641 }
2642
2643 if (!ValidateRobustBufferSize(context, bufSize, *length))
2644 {
2645 return false;
2646 }
2647
2648 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002649}
2650
2651bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2652{
2653 if (!context->getExtensions().disjointTimerQuery)
2654 {
Jamie Madill437fa652016-05-03 15:13:24 -04002655 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002656 return false;
2657 }
Geoff Lang2186c382016-10-14 10:54:54 -04002658 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2659}
2660
2661bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2662 GLuint id,
2663 GLenum pname,
2664 GLsizei bufSize,
2665 GLsizei *length,
2666 GLuint64 *params)
2667{
2668 if (!context->getExtensions().disjointTimerQuery)
2669 {
2670 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2671 return false;
2672 }
2673
2674 if (!ValidateRobustEntryPoint(context, bufSize))
2675 {
2676 return false;
2677 }
2678
2679 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2680 {
2681 return false;
2682 }
2683
2684 if (!ValidateRobustBufferSize(context, bufSize, *length))
2685 {
2686 return false;
2687 }
2688
2689 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002690}
2691
Jamie Madill62d31cb2015-09-11 13:25:51 -04002692static bool ValidateUniformCommonBase(gl::Context *context,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002693 gl::Program *program,
Jamie Madill62d31cb2015-09-11 13:25:51 -04002694 GLenum targetUniformType,
2695 GLint location,
2696 GLsizei count,
2697 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002698{
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002699 // TODO(Jiajia): Add image uniform check in future.
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002700 if (count < 0)
2701 {
Jamie Madill437fa652016-05-03 15:13:24 -04002702 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002703 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002704 }
2705
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002706 if (!program || !program->isLinked())
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002707 {
Jamie Madill437fa652016-05-03 15:13:24 -04002708 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002709 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002710 }
2711
Jamie Madillac4e9c32017-01-13 14:07:12 -05002712 if (location == -1)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002713 {
2714 // Silently ignore the uniform command
2715 return false;
2716 }
2717
Jamie Madillac4e9c32017-01-13 14:07:12 -05002718 const auto &uniformLocations = program->getUniformLocations();
2719 size_t castedLocation = static_cast<size_t>(location);
2720 if (castedLocation >= uniformLocations.size())
2721 {
2722 context->handleError(Error(GL_INVALID_OPERATION, "Invalid uniform location"));
2723 return false;
2724 }
2725
2726 const auto &uniformLocation = uniformLocations[castedLocation];
2727 if (uniformLocation.ignored)
2728 {
2729 // Silently ignore the uniform command
2730 return false;
2731 }
2732
2733 if (!uniformLocation.used)
Jamie Madill36398922014-05-20 14:51:53 -04002734 {
Jamie Madill437fa652016-05-03 15:13:24 -04002735 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002736 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002737 }
2738
Jamie Madillac4e9c32017-01-13 14:07:12 -05002739 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
Jamie Madill36398922014-05-20 14:51:53 -04002740
2741 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002742 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002743 {
Jamie Madill437fa652016-05-03 15:13:24 -04002744 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002745 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002746 }
2747
Jamie Madill62d31cb2015-09-11 13:25:51 -04002748 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002749 return true;
2750}
2751
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002752bool ValidateProgramUniform(gl::Context *context,
2753 GLenum uniformType,
2754 GLuint program,
2755 GLint location,
2756 GLsizei count)
2757{
2758 // Check for ES31 program uniform entry points
2759 if (context->getClientVersion() < Version(3, 1))
2760 {
2761 context->handleError(Error(GL_INVALID_OPERATION));
2762 return false;
2763 }
2764
2765 const LinkedUniform *uniform = nullptr;
2766 gl::Program *programObject = GetValidProgram(context, program);
2767 if (!ValidateUniformCommonBase(context, programObject, uniformType, location, count, &uniform))
2768 {
2769 return false;
2770 }
2771
2772 GLenum targetBoolType = VariableBoolVectorType(uniformType);
2773 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
2774 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2775 {
2776 context->handleError(Error(GL_INVALID_OPERATION));
2777 return false;
2778 }
2779
2780 return true;
2781}
2782
2783bool ValidateProgramUniformMatrix(gl::Context *context,
2784 GLenum matrixType,
2785 GLuint program,
2786 GLint location,
2787 GLsizei count,
2788 GLboolean transpose)
2789{
2790 // Check for ES31 program uniform entry points
2791 if (context->getClientVersion() < Version(3, 1))
2792 {
2793 context->handleError(Error(GL_INVALID_OPERATION));
2794 return false;
2795 }
2796
2797 const LinkedUniform *uniform = nullptr;
2798 gl::Program *programObject = GetValidProgram(context, program);
2799 if (!ValidateUniformCommonBase(context, programObject, matrixType, location, count, &uniform))
2800 {
2801 return false;
2802 }
2803
2804 if (uniform->type != matrixType)
2805 {
2806 context->handleError(Error(GL_INVALID_OPERATION));
2807 return false;
2808 }
2809
2810 return true;
2811}
2812
Jamie Madillaa981bd2014-05-20 10:55:55 -04002813bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2814{
2815 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002816 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2817 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002818 {
Jamie Madill437fa652016-05-03 15:13:24 -04002819 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002820 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002821 }
2822
Jamie Madill62d31cb2015-09-11 13:25:51 -04002823 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002824 gl::Program *program = context->getGLState().getProgram();
2825 if (!ValidateUniformCommonBase(context, program, uniformType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002826 {
2827 return false;
2828 }
2829
He Yunchaoced53ae2016-11-29 15:00:51 +08002830 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002831 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002832 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2833 {
Jamie Madill437fa652016-05-03 15:13:24 -04002834 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002835 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002836 }
2837
2838 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002839}
2840
He Yunchaoced53ae2016-11-29 15:00:51 +08002841bool ValidateUniformMatrix(gl::Context *context,
2842 GLenum matrixType,
2843 GLint location,
2844 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002845 GLboolean transpose)
2846{
2847 // Check for ES3 uniform entry points
2848 int rows = VariableRowCount(matrixType);
2849 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002850 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002851 {
Jamie Madill437fa652016-05-03 15:13:24 -04002852 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002853 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002854 }
2855
Martin Radev1be913c2016-07-11 17:59:16 +03002856 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002857 {
Jamie Madill437fa652016-05-03 15:13:24 -04002858 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002859 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002860 }
2861
Jamie Madill62d31cb2015-09-11 13:25:51 -04002862 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002863 gl::Program *program = context->getGLState().getProgram();
2864 if (!ValidateUniformCommonBase(context, program, matrixType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002865 {
2866 return false;
2867 }
2868
2869 if (uniform->type != matrixType)
2870 {
Jamie Madill437fa652016-05-03 15:13:24 -04002871 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002872 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002873 }
2874
2875 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002876}
2877
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002878bool ValidateStateQuery(ValidationContext *context,
2879 GLenum pname,
2880 GLenum *nativeType,
2881 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002882{
2883 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2884 {
Jamie Madill437fa652016-05-03 15:13:24 -04002885 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002886 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002887 }
2888
Jamie Madill0af26e12015-03-05 19:54:33 -05002889 const Caps &caps = context->getCaps();
2890
Jamie Madill893ab082014-05-16 16:56:10 -04002891 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2892 {
2893 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2894
Jamie Madill0af26e12015-03-05 19:54:33 -05002895 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002896 {
Jamie Madill437fa652016-05-03 15:13:24 -04002897 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002898 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002899 }
2900 }
2901
2902 switch (pname)
2903 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002904 case GL_TEXTURE_BINDING_2D:
2905 case GL_TEXTURE_BINDING_CUBE_MAP:
2906 case GL_TEXTURE_BINDING_3D:
2907 case GL_TEXTURE_BINDING_2D_ARRAY:
2908 break;
2909 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2910 if (!context->getExtensions().eglStreamConsumerExternal &&
2911 !context->getExtensions().eglImageExternal)
2912 {
2913 context->handleError(Error(GL_INVALID_ENUM,
2914 "Neither NV_EGL_stream_consumer_external nor "
2915 "GL_OES_EGL_image_external extensions enabled"));
2916 return false;
2917 }
2918 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002919
He Yunchaoced53ae2016-11-29 15:00:51 +08002920 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2921 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002922 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002923 if (context->getGLState().getReadFramebuffer()->checkStatus(
2924 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002925 {
Jamie Madill437fa652016-05-03 15:13:24 -04002926 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002927 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002928 }
2929
Jamie Madill51f40ec2016-06-15 14:06:00 -04002930 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2931 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002932
2933 if (framebuffer->getReadBufferState() == GL_NONE)
2934 {
2935 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2936 return false;
2937 }
2938
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002939 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002940 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002941 {
Jamie Madill437fa652016-05-03 15:13:24 -04002942 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002943 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002944 }
2945 }
2946 break;
2947
He Yunchaoced53ae2016-11-29 15:00:51 +08002948 default:
2949 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002950 }
2951
2952 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002953 if (*numParams == 0)
2954 {
2955 return false;
2956 }
2957
2958 return true;
2959}
2960
2961bool ValidateRobustStateQuery(ValidationContext *context,
2962 GLenum pname,
2963 GLsizei bufSize,
2964 GLenum *nativeType,
2965 unsigned int *numParams)
2966{
2967 if (!ValidateRobustEntryPoint(context, bufSize))
2968 {
2969 return false;
2970 }
2971
2972 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2973 {
2974 return false;
2975 }
2976
2977 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002978 {
2979 return false;
2980 }
2981
2982 return true;
2983}
2984
Jamie Madillc29968b2016-01-20 11:17:23 -05002985bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2986 GLenum target,
2987 GLint level,
2988 GLenum internalformat,
2989 bool isSubImage,
2990 GLint xoffset,
2991 GLint yoffset,
2992 GLint zoffset,
2993 GLint x,
2994 GLint y,
2995 GLsizei width,
2996 GLsizei height,
2997 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002998 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002999{
Jamie Madill560a8d82014-05-21 13:06:20 -04003000 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
3001 {
Jamie Madill437fa652016-05-03 15:13:24 -04003002 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003003 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003004 }
3005
He Yunchaoced53ae2016-11-29 15:00:51 +08003006 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
3007 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04003008 {
Jamie Madill437fa652016-05-03 15:13:24 -04003009 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003010 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003011 }
3012
3013 if (border != 0)
3014 {
Jamie Madill437fa652016-05-03 15:13:24 -04003015 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003016 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003017 }
3018
3019 if (!ValidMipLevel(context, target, level))
3020 {
Jamie Madill437fa652016-05-03 15:13:24 -04003021 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003022 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003023 }
3024
Jamie Madill51f40ec2016-06-15 14:06:00 -04003025 const auto &state = context->getGLState();
3026 auto readFramebuffer = state.getReadFramebuffer();
3027 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003028 {
Jamie Madill437fa652016-05-03 15:13:24 -04003029 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003030 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003031 }
3032
Jamie Madill51f40ec2016-06-15 14:06:00 -04003033 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003034 {
Jamie Madill437fa652016-05-03 15:13:24 -04003035 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003036 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003037 }
3038
Martin Radev138064f2016-07-15 12:03:41 +03003039 if (readFramebuffer->getReadBufferState() == GL_NONE)
3040 {
3041 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3042 return false;
3043 }
3044
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003045 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3046 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003047 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003048 // situation is an application error that would lead to a crash in ANGLE.
3049 if (readFramebuffer->getReadColorbuffer() == nullptr)
3050 {
3051 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3052 return false;
3053 }
3054
Geoff Langaae65a42014-05-26 12:43:44 -04003055 const gl::Caps &caps = context->getCaps();
3056
Geoff Langaae65a42014-05-26 12:43:44 -04003057 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003058 switch (target)
3059 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003060 case GL_TEXTURE_2D:
3061 maxDimension = caps.max2DTextureSize;
3062 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003063
He Yunchaoced53ae2016-11-29 15:00:51 +08003064 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3065 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3066 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3067 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3068 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3069 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3070 maxDimension = caps.maxCubeMapTextureSize;
3071 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003072
He Yunchaoced53ae2016-11-29 15:00:51 +08003073 case GL_TEXTURE_2D_ARRAY:
3074 maxDimension = caps.max2DTextureSize;
3075 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003076
He Yunchaoced53ae2016-11-29 15:00:51 +08003077 case GL_TEXTURE_3D:
3078 maxDimension = caps.max3DTextureSize;
3079 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003080
He Yunchaoced53ae2016-11-29 15:00:51 +08003081 default:
3082 context->handleError(Error(GL_INVALID_ENUM));
3083 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003084 }
3085
Jamie Madillc29968b2016-01-20 11:17:23 -05003086 gl::Texture *texture =
3087 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003088 if (!texture)
3089 {
Jamie Madill437fa652016-05-03 15:13:24 -04003090 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003091 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003092 }
3093
Geoff Lang69cce582015-09-17 13:20:36 -04003094 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003095 {
Jamie Madill437fa652016-05-03 15:13:24 -04003096 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003097 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003098 }
3099
Geoff Lang5d601382014-07-22 15:14:06 -04003100 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3101
3102 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003103 {
Jamie Madill437fa652016-05-03 15:13:24 -04003104 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003105 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003106 }
3107
Geoff Langa9be0dc2014-12-17 12:34:40 -05003108 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003109 {
Jamie Madill437fa652016-05-03 15:13:24 -04003110 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003111 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003112 }
3113
3114 if (isSubImage)
3115 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003116 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3117 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3118 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003119 {
Jamie Madill437fa652016-05-03 15:13:24 -04003120 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003121 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003122 }
3123 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003124 else
3125 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003126 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003127 {
Jamie Madill437fa652016-05-03 15:13:24 -04003128 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003129 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003130 }
3131
Geoff Langeb66a6e2016-10-31 13:06:12 -04003132 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003133 {
Jamie Madill437fa652016-05-03 15:13:24 -04003134 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003135 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003136 }
3137
3138 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003139 if (static_cast<int>(width) > maxLevelDimension ||
3140 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003141 {
Jamie Madill437fa652016-05-03 15:13:24 -04003142 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003143 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003144 }
3145 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003146
Jamie Madill0c8abca2016-07-22 20:21:26 -04003147 if (textureFormatOut)
3148 {
3149 *textureFormatOut = texture->getFormat(target, level);
3150 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003151
3152 // Detect texture copying feedback loops for WebGL.
3153 if (context->getExtensions().webglCompatibility)
3154 {
3155 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level))
3156 {
3157 context->handleError(Error(GL_INVALID_OPERATION,
3158 "Texture copying feedback loop formed between Framebuffer "
3159 "and specified Texture level."));
3160 return false;
3161 }
3162 }
3163
Jamie Madill560a8d82014-05-21 13:06:20 -04003164 return true;
3165}
3166
Jiajia Qind9671222016-11-29 16:30:31 +08003167bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003168{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003169 switch (mode)
3170 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003171 case GL_POINTS:
3172 case GL_LINES:
3173 case GL_LINE_LOOP:
3174 case GL_LINE_STRIP:
3175 case GL_TRIANGLES:
3176 case GL_TRIANGLE_STRIP:
3177 case GL_TRIANGLE_FAN:
3178 break;
3179 default:
3180 context->handleError(Error(GL_INVALID_ENUM));
3181 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003182 }
3183
Jamie Madill250d33f2014-06-06 17:09:03 -04003184 if (count < 0)
3185 {
Jamie Madill437fa652016-05-03 15:13:24 -04003186 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003187 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003188 }
3189
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003190 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003191
Jamie Madill250d33f2014-06-06 17:09:03 -04003192 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003193 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003194 {
Jamie Madill437fa652016-05-03 15:13:24 -04003195 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003196 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003197 }
3198
Jamie Madillcbcde722017-01-06 14:50:00 -05003199 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3200 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003201 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003202 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3203 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003204 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003205 const FramebufferAttachment *dsAttachment =
3206 framebuffer->getStencilOrDepthStencilAttachment();
3207 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003208 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003209 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003210
3211 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3212 bool differentWritemasks =
3213 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3214 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3215 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3216 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3217
3218 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003219 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003220 if (!context->getExtensions().webglCompatibility)
3221 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05003222 ERR() << "This ANGLE implementation does not support separate front/back stencil "
3223 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05003224 }
Jamie Madill437fa652016-05-03 15:13:24 -04003225 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003226 return false;
3227 }
Jamie Madillac528012014-06-20 13:21:23 -04003228 }
3229
Jamie Madill51f40ec2016-06-15 14:06:00 -04003230 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003231 {
Jamie Madill437fa652016-05-03 15:13:24 -04003232 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003233 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003234 }
3235
Geoff Lang7dd2e102014-11-10 15:19:26 -05003236 gl::Program *program = state.getProgram();
3237 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003238 {
Jamie Madill437fa652016-05-03 15:13:24 -04003239 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003240 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003241 }
3242
Geoff Lang7dd2e102014-11-10 15:19:26 -05003243 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003244 {
Jamie Madill437fa652016-05-03 15:13:24 -04003245 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003246 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003247 }
3248
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003249 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003250 for (unsigned int uniformBlockIndex = 0;
3251 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003252 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003253 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003254 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003255 const OffsetBindingPointer<Buffer> &uniformBuffer =
3256 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003257
Geoff Lang5d124a62015-09-15 13:03:27 -04003258 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003259 {
3260 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003261 context->handleError(
3262 Error(GL_INVALID_OPERATION,
3263 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003264 return false;
3265 }
3266
Geoff Lang5d124a62015-09-15 13:03:27 -04003267 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003268 if (uniformBufferSize == 0)
3269 {
3270 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003271 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003272 }
3273
Jamie Madill62d31cb2015-09-11 13:25:51 -04003274 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003275 {
3276 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003277 context->handleError(
3278 Error(GL_INVALID_OPERATION,
3279 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003280 return false;
3281 }
3282 }
3283
Jamie Madilla4595b82017-01-11 17:36:34 -05003284 // Detect rendering feedback loops for WebGL.
3285 if (context->getExtensions().webglCompatibility)
3286 {
3287 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3288 {
3289 context->handleError(
3290 Error(GL_INVALID_OPERATION,
3291 "Rendering feedback loop formed between Framebuffer and active Texture."));
3292 return false;
3293 }
3294 }
3295
Jamie Madill250d33f2014-06-06 17:09:03 -04003296 // No-op if zero count
3297 return (count > 0);
3298}
3299
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003300bool ValidateDrawArrays(ValidationContext *context,
3301 GLenum mode,
3302 GLint first,
3303 GLsizei count,
3304 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003305{
Jamie Madillfd716582014-06-06 17:09:04 -04003306 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003307 {
Jamie Madill437fa652016-05-03 15:13:24 -04003308 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003309 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003310 }
3311
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003312 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003313 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003314 if (curTransformFeedback && curTransformFeedback->isActive() &&
3315 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003316 {
3317 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003318 // that does not match the current transform feedback object's draw mode (if transform
3319 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003320 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003321 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003322 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003323 }
3324
Jiajia Qind9671222016-11-29 16:30:31 +08003325 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003326 {
3327 return false;
3328 }
3329
Corentin Wallez71168a02016-12-19 15:11:18 -08003330 // Check the computation of maxVertex doesn't overflow.
3331 // - first < 0 or count < 0 have been checked as an error condition
3332 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3333 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3334 ASSERT(count > 0 && first >= 0);
3335 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3336 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003337 {
3338 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3339 return false;
3340 }
3341
Corentin Wallez71168a02016-12-19 15:11:18 -08003342 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003343 {
3344 return false;
3345 }
3346
3347 return true;
3348}
3349
He Yunchaoced53ae2016-11-29 15:00:51 +08003350bool ValidateDrawArraysInstanced(Context *context,
3351 GLenum mode,
3352 GLint first,
3353 GLsizei count,
3354 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003355{
3356 if (primcount < 0)
3357 {
Jamie Madill437fa652016-05-03 15:13:24 -04003358 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003359 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003360 }
3361
Jamie Madill2b976812014-08-25 15:47:49 -04003362 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003363 {
3364 return false;
3365 }
3366
3367 // No-op if zero primitive count
3368 return (primcount > 0);
3369}
3370
Geoff Lang87a93302014-09-16 13:29:43 -04003371static bool ValidateDrawInstancedANGLE(Context *context)
3372{
3373 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003374 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003375
Geoff Lang7dd2e102014-11-10 15:19:26 -05003376 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003377
3378 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003379 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003380 {
3381 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003382 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003383 {
3384 return true;
3385 }
3386 }
3387
Jamie Madill437fa652016-05-03 15:13:24 -04003388 context->handleError(Error(GL_INVALID_OPERATION,
3389 "ANGLE_instanced_arrays requires that at least one active attribute"
3390 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003391 return false;
3392}
3393
He Yunchaoced53ae2016-11-29 15:00:51 +08003394bool ValidateDrawArraysInstancedANGLE(Context *context,
3395 GLenum mode,
3396 GLint first,
3397 GLsizei count,
3398 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003399{
3400 if (!ValidateDrawInstancedANGLE(context))
3401 {
3402 return false;
3403 }
3404
3405 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3406}
3407
Jiajia Qind9671222016-11-29 16:30:31 +08003408bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003409{
Jamie Madill250d33f2014-06-06 17:09:03 -04003410 switch (type)
3411 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003412 case GL_UNSIGNED_BYTE:
3413 case GL_UNSIGNED_SHORT:
3414 break;
3415 case GL_UNSIGNED_INT:
3416 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3417 {
3418 context->handleError(Error(GL_INVALID_ENUM));
3419 return false;
3420 }
3421 break;
3422 default:
3423 context->handleError(Error(GL_INVALID_ENUM));
3424 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003425 }
3426
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003427 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003428
3429 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003430 if (curTransformFeedback && curTransformFeedback->isActive() &&
3431 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003432 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003433 // It is an invalid operation to call DrawElements, DrawRangeElements or
3434 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003435 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003436 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003437 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003438 }
3439
Jiajia Qind9671222016-11-29 16:30:31 +08003440 return true;
3441}
3442
3443bool ValidateDrawElements(ValidationContext *context,
3444 GLenum mode,
3445 GLsizei count,
3446 GLenum type,
3447 const GLvoid *indices,
3448 GLsizei primcount,
3449 IndexRange *indexRangeOut)
3450{
3451 if (!ValidateDrawElementsBase(context, type))
3452 return false;
3453
3454 const State &state = context->getGLState();
3455
Jamie Madill250d33f2014-06-06 17:09:03 -04003456 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003457 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003458 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003459 context->handleError(Error(GL_INVALID_OPERATION, "Index buffer is mapped."));
Geoff Langb1196682014-07-23 13:47:29 -04003460 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003461 }
3462
He Yunchaoced53ae2016-11-29 15:00:51 +08003463 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003464 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003465
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003466 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3467
3468 if (context->getExtensions().webglCompatibility)
3469 {
3470 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3471 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3472 {
3473 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3474 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3475 // data type passed to the call, or an INVALID_OPERATION error is generated.
3476 context->handleError(Error(GL_INVALID_OPERATION,
3477 "indices must be a multiple of the element type size."));
3478 return false;
3479 }
3480 if (!elementArrayBuffer && count > 0)
3481 {
3482 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3483 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3484 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3485 context->handleError(Error(GL_INVALID_OPERATION,
3486 "There is no element array buffer bound and count > 0."));
3487 return false;
3488 }
3489 }
3490
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003491 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003492 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003493 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003494 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003495 GLint64 offset = reinterpret_cast<GLint64>(indices);
3496 GLint64 byteCount =
3497 static_cast<GLint64>(typeBytes) * static_cast<GLint64>(count) + offset;
3498
3499 // check for integer overflows
3500 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeBytes) ||
3501 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3502 {
3503 context->handleError(Error(GL_OUT_OF_MEMORY, "Integer overflow."));
3504 return false;
3505 }
3506
3507 // Check for reading past the end of the bound buffer object
3508 if (byteCount > elementArrayBuffer->getSize())
3509 {
3510 context->handleError(
3511 Error(GL_INVALID_OPERATION, "Index buffer is not big enough for the draw."));
3512 return false;
3513 }
3514 }
3515 else if (!indices)
3516 {
3517 // This is an application error that would normally result in a crash,
3518 // but we catch it and return an error
3519 context->handleError(
3520 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003521 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003522 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003523 }
3524
Jiajia Qind9671222016-11-29 16:30:31 +08003525 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003526 {
3527 return false;
3528 }
3529
Jamie Madill2b976812014-08-25 15:47:49 -04003530 // Use max index to validate if our vertex buffers are large enough for the pull.
3531 // TODO: offer fast path, with disabled index validation.
3532 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3533 if (elementArrayBuffer)
3534 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003535 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003536 Error error =
3537 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3538 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003539 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003540 {
Jamie Madill437fa652016-05-03 15:13:24 -04003541 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003542 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003543 }
3544 }
3545 else
3546 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003547 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003548 }
3549
Jamie Madille79b1e12015-11-04 16:36:37 -05003550 // If we use an index greater than our maximum supported index range, return an error.
3551 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3552 // return an error if possible here.
3553 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3554 {
Jamie Madill437fa652016-05-03 15:13:24 -04003555 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003556 return false;
3557 }
3558
Corentin Wallez92db6942016-12-09 13:10:36 -05003559 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3560 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003561 {
3562 return false;
3563 }
3564
Geoff Lang3edfe032015-09-04 16:38:24 -04003565 // No op if there are no real indices in the index data (all are primitive restart).
3566 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003567}
3568
Geoff Langb1196682014-07-23 13:47:29 -04003569bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003570 GLenum mode,
3571 GLsizei count,
3572 GLenum type,
3573 const GLvoid *indices,
3574 GLsizei primcount,
3575 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003576{
3577 if (primcount < 0)
3578 {
Jamie Madill437fa652016-05-03 15:13:24 -04003579 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003580 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003581 }
3582
Jamie Madill2b976812014-08-25 15:47:49 -04003583 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003584 {
3585 return false;
3586 }
3587
3588 // No-op zero primitive count
3589 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003590}
3591
Geoff Lang3edfe032015-09-04 16:38:24 -04003592bool ValidateDrawElementsInstancedANGLE(Context *context,
3593 GLenum mode,
3594 GLsizei count,
3595 GLenum type,
3596 const GLvoid *indices,
3597 GLsizei primcount,
3598 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003599{
3600 if (!ValidateDrawInstancedANGLE(context))
3601 {
3602 return false;
3603 }
3604
He Yunchaoced53ae2016-11-29 15:00:51 +08003605 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3606 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003607}
3608
He Yunchaoced53ae2016-11-29 15:00:51 +08003609bool ValidateFramebufferTextureBase(Context *context,
3610 GLenum target,
3611 GLenum attachment,
3612 GLuint texture,
3613 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003614{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003615 if (!ValidFramebufferTarget(target))
3616 {
Jamie Madill437fa652016-05-03 15:13:24 -04003617 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003618 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003619 }
3620
3621 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003622 {
3623 return false;
3624 }
3625
Jamie Madill55ec3b12014-07-03 10:38:57 -04003626 if (texture != 0)
3627 {
3628 gl::Texture *tex = context->getTexture(texture);
3629
3630 if (tex == NULL)
3631 {
Jamie Madill437fa652016-05-03 15:13:24 -04003632 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003633 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003634 }
3635
3636 if (level < 0)
3637 {
Jamie Madill437fa652016-05-03 15:13:24 -04003638 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003639 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003640 }
3641 }
3642
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003643 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003644 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003645
Jamie Madill84115c92015-04-23 15:00:07 -04003646 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003647 {
Jamie Madill437fa652016-05-03 15:13:24 -04003648 context->handleError(
3649 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003650 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003651 }
3652
3653 return true;
3654}
3655
He Yunchaoced53ae2016-11-29 15:00:51 +08003656bool ValidateFramebufferTexture2D(Context *context,
3657 GLenum target,
3658 GLenum attachment,
3659 GLenum textarget,
3660 GLuint texture,
3661 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003662{
He Yunchaoced53ae2016-11-29 15:00:51 +08003663 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3664 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003665 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3666 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003667 {
Jamie Madill437fa652016-05-03 15:13:24 -04003668 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003669 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003670 }
3671
3672 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003673 {
3674 return false;
3675 }
3676
Jamie Madill55ec3b12014-07-03 10:38:57 -04003677 if (texture != 0)
3678 {
3679 gl::Texture *tex = context->getTexture(texture);
3680 ASSERT(tex);
3681
Jamie Madill2a6564e2014-07-11 09:53:19 -04003682 const gl::Caps &caps = context->getCaps();
3683
Jamie Madill55ec3b12014-07-03 10:38:57 -04003684 switch (textarget)
3685 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003686 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003687 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003688 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003689 {
Jamie Madill437fa652016-05-03 15:13:24 -04003690 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003691 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003692 }
3693 if (tex->getTarget() != GL_TEXTURE_2D)
3694 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003695 context->handleError(Error(GL_INVALID_OPERATION,
3696 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003697 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003698 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003699 }
3700 break;
3701
He Yunchaoced53ae2016-11-29 15:00:51 +08003702 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3703 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3704 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3705 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3706 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3707 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003708 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003709 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003710 {
Jamie Madill437fa652016-05-03 15:13:24 -04003711 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003712 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003713 }
3714 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3715 {
JiangYizhoubddc46b2016-12-09 09:50:51 +08003716 context->handleError(Error(GL_INVALID_OPERATION,
3717 "Textarget must match the texture target type."));
3718 return false;
3719 }
3720 }
3721 break;
3722
3723 case GL_TEXTURE_2D_MULTISAMPLE:
3724 {
3725 if (context->getClientVersion() < ES_3_1)
3726 {
3727 context->handleError(Error(GL_INVALID_OPERATION,
3728 "Texture target requires at least OpenGL ES 3.1."));
3729 return false;
3730 }
3731
3732 if (level != 0)
3733 {
3734 context->handleError(
3735 Error(GL_INVALID_VALUE, "Level must be 0 for TEXTURE_2D_MULTISAMPLE."));
3736 return false;
3737 }
3738 if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
3739 {
3740 context->handleError(Error(GL_INVALID_OPERATION,
3741 "Textarget must match the texture target type."));
Geoff Langb1196682014-07-23 13:47:29 -04003742 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003743 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003744 }
3745 break;
3746
He Yunchaoced53ae2016-11-29 15:00:51 +08003747 default:
3748 context->handleError(Error(GL_INVALID_ENUM));
3749 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003750 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003751
Jamie Madilla3944d42016-07-22 22:13:26 -04003752 const Format &format = tex->getFormat(textarget, level);
3753 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003754 {
Jamie Madill437fa652016-05-03 15:13:24 -04003755 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003756 return false;
3757 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003758 }
3759
Jamie Madill570f7c82014-07-03 10:38:54 -04003760 return true;
3761}
3762
Geoff Langb1196682014-07-23 13:47:29 -04003763bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003764{
3765 if (program == 0)
3766 {
Jamie Madill437fa652016-05-03 15:13:24 -04003767 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003768 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003769 }
3770
Dian Xiang769769a2015-09-09 15:20:08 -07003771 gl::Program *programObject = GetValidProgram(context, program);
3772 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003773 {
3774 return false;
3775 }
3776
Jamie Madill0063c512014-08-25 15:47:53 -04003777 if (!programObject || !programObject->isLinked())
3778 {
Jamie Madill437fa652016-05-03 15:13:24 -04003779 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003780 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003781 }
3782
Geoff Lang7dd2e102014-11-10 15:19:26 -05003783 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003784 {
Jamie Madill437fa652016-05-03 15:13:24 -04003785 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003786 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003787 }
3788
Jamie Madill0063c512014-08-25 15:47:53 -04003789 return true;
3790}
3791
He Yunchaoced53ae2016-11-29 15:00:51 +08003792bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003793{
3794 return ValidateGetUniformBase(context, program, location);
3795}
3796
He Yunchaoced53ae2016-11-29 15:00:51 +08003797bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003798{
Jamie Madill78f41802014-08-25 15:47:55 -04003799 return ValidateGetUniformBase(context, program, location);
3800}
3801
Geoff Langf41d0ee2016-10-07 13:04:23 -04003802static bool ValidateSizedGetUniform(Context *context,
3803 GLuint program,
3804 GLint location,
3805 GLsizei bufSize,
3806 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003807{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003808 if (length)
3809 {
3810 *length = 0;
3811 }
3812
Jamie Madill78f41802014-08-25 15:47:55 -04003813 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003814 {
Jamie Madill78f41802014-08-25 15:47:55 -04003815 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003816 }
3817
Geoff Langf41d0ee2016-10-07 13:04:23 -04003818 if (bufSize < 0)
3819 {
3820 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3821 return false;
3822 }
3823
Jamie Madilla502c742014-08-28 17:19:13 -04003824 gl::Program *programObject = context->getProgram(program);
3825 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003826
Jamie Madill78f41802014-08-25 15:47:55 -04003827 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003828 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003829 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003830 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003831 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003832 context->handleError(
3833 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003834 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003835 }
3836
Geoff Langf41d0ee2016-10-07 13:04:23 -04003837 if (length)
3838 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003839 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003840 }
3841
Jamie Madill0063c512014-08-25 15:47:53 -04003842 return true;
3843}
3844
He Yunchaoced53ae2016-11-29 15:00:51 +08003845bool ValidateGetnUniformfvEXT(Context *context,
3846 GLuint program,
3847 GLint location,
3848 GLsizei bufSize,
3849 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003850{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003851 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003852}
3853
He Yunchaoced53ae2016-11-29 15:00:51 +08003854bool ValidateGetnUniformivEXT(Context *context,
3855 GLuint program,
3856 GLint location,
3857 GLsizei bufSize,
3858 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003859{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003860 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3861}
3862
3863bool ValidateGetUniformfvRobustANGLE(Context *context,
3864 GLuint program,
3865 GLint location,
3866 GLsizei bufSize,
3867 GLsizei *length,
3868 GLfloat *params)
3869{
3870 if (!ValidateRobustEntryPoint(context, bufSize))
3871 {
3872 return false;
3873 }
3874
3875 // bufSize is validated in ValidateSizedGetUniform
3876 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3877}
3878
3879bool ValidateGetUniformivRobustANGLE(Context *context,
3880 GLuint program,
3881 GLint location,
3882 GLsizei bufSize,
3883 GLsizei *length,
3884 GLint *params)
3885{
3886 if (!ValidateRobustEntryPoint(context, bufSize))
3887 {
3888 return false;
3889 }
3890
3891 // bufSize is validated in ValidateSizedGetUniform
3892 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3893}
3894
3895bool ValidateGetUniformuivRobustANGLE(Context *context,
3896 GLuint program,
3897 GLint location,
3898 GLsizei bufSize,
3899 GLsizei *length,
3900 GLuint *params)
3901{
3902 if (!ValidateRobustEntryPoint(context, bufSize))
3903 {
3904 return false;
3905 }
3906
3907 if (context->getClientMajorVersion() < 3)
3908 {
3909 context->handleError(
3910 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3911 return false;
3912 }
3913
3914 // bufSize is validated in ValidateSizedGetUniform
3915 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003916}
3917
He Yunchaoced53ae2016-11-29 15:00:51 +08003918bool ValidateDiscardFramebufferBase(Context *context,
3919 GLenum target,
3920 GLsizei numAttachments,
3921 const GLenum *attachments,
3922 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003923{
3924 if (numAttachments < 0)
3925 {
Jamie Madill437fa652016-05-03 15:13:24 -04003926 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003927 return false;
3928 }
3929
3930 for (GLsizei i = 0; i < numAttachments; ++i)
3931 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003932 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003933 {
3934 if (defaultFramebuffer)
3935 {
Jamie Madill437fa652016-05-03 15:13:24 -04003936 context->handleError(Error(
3937 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003938 return false;
3939 }
3940
3941 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3942 {
Jamie Madill437fa652016-05-03 15:13:24 -04003943 context->handleError(Error(GL_INVALID_OPERATION,
3944 "Requested color attachment is greater than the maximum "
3945 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003946 return false;
3947 }
3948 }
3949 else
3950 {
3951 switch (attachments[i])
3952 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003953 case GL_DEPTH_ATTACHMENT:
3954 case GL_STENCIL_ATTACHMENT:
3955 case GL_DEPTH_STENCIL_ATTACHMENT:
3956 if (defaultFramebuffer)
3957 {
3958 context->handleError(
3959 Error(GL_INVALID_ENUM,
3960 "Invalid attachment when the default framebuffer is bound"));
3961 return false;
3962 }
3963 break;
3964 case GL_COLOR:
3965 case GL_DEPTH:
3966 case GL_STENCIL:
3967 if (!defaultFramebuffer)
3968 {
3969 context->handleError(
3970 Error(GL_INVALID_ENUM,
3971 "Invalid attachment when the default framebuffer is not bound"));
3972 return false;
3973 }
3974 break;
3975 default:
3976 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003977 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003978 }
3979 }
3980 }
3981
3982 return true;
3983}
3984
Austin Kinross6ee1e782015-05-29 17:05:37 -07003985bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3986{
3987 // Note that debug marker calls must not set error state
3988
3989 if (length < 0)
3990 {
3991 return false;
3992 }
3993
3994 if (marker == nullptr)
3995 {
3996 return false;
3997 }
3998
3999 return true;
4000}
4001
4002bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
4003{
4004 // Note that debug marker calls must not set error state
4005
4006 if (length < 0)
4007 {
4008 return false;
4009 }
4010
4011 if (length > 0 && marker == nullptr)
4012 {
4013 return false;
4014 }
4015
4016 return true;
4017}
4018
Geoff Langdcab33b2015-07-21 13:03:16 -04004019bool ValidateEGLImageTargetTexture2DOES(Context *context,
4020 egl::Display *display,
4021 GLenum target,
4022 egl::Image *image)
4023{
Geoff Langa8406172015-07-21 16:53:39 -04004024 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
4025 {
Jamie Madill437fa652016-05-03 15:13:24 -04004026 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004027 return false;
4028 }
4029
4030 switch (target)
4031 {
4032 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04004033 if (!context->getExtensions().eglImage)
4034 {
4035 context->handleError(Error(
4036 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
4037 }
4038 break;
4039
4040 case GL_TEXTURE_EXTERNAL_OES:
4041 if (!context->getExtensions().eglImageExternal)
4042 {
4043 context->handleError(Error(
4044 GL_INVALID_ENUM,
4045 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
4046 }
Geoff Langa8406172015-07-21 16:53:39 -04004047 break;
4048
4049 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004050 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04004051 return false;
4052 }
4053
4054 if (!display->isValidImage(image))
4055 {
Jamie Madill437fa652016-05-03 15:13:24 -04004056 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004057 return false;
4058 }
4059
4060 if (image->getSamples() > 0)
4061 {
Jamie Madill437fa652016-05-03 15:13:24 -04004062 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004063 "cannot create a 2D texture from a multisampled EGL image."));
4064 return false;
4065 }
4066
Jamie Madilla3944d42016-07-22 22:13:26 -04004067 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004068 if (!textureCaps.texturable)
4069 {
Jamie Madill437fa652016-05-03 15:13:24 -04004070 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004071 "EGL image internal format is not supported as a texture."));
4072 return false;
4073 }
4074
Geoff Langdcab33b2015-07-21 13:03:16 -04004075 return true;
4076}
4077
4078bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4079 egl::Display *display,
4080 GLenum target,
4081 egl::Image *image)
4082{
Geoff Langa8406172015-07-21 16:53:39 -04004083 if (!context->getExtensions().eglImage)
4084 {
Jamie Madill437fa652016-05-03 15:13:24 -04004085 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004086 return false;
4087 }
4088
4089 switch (target)
4090 {
4091 case GL_RENDERBUFFER:
4092 break;
4093
4094 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004095 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004096 return false;
4097 }
4098
4099 if (!display->isValidImage(image))
4100 {
Jamie Madill437fa652016-05-03 15:13:24 -04004101 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004102 return false;
4103 }
4104
Jamie Madilla3944d42016-07-22 22:13:26 -04004105 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004106 if (!textureCaps.renderable)
4107 {
Jamie Madill437fa652016-05-03 15:13:24 -04004108 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004109 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4110 return false;
4111 }
4112
Geoff Langdcab33b2015-07-21 13:03:16 -04004113 return true;
4114}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004115
4116bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4117{
Geoff Lang36167ab2015-12-07 10:27:14 -05004118 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004119 {
4120 // The default VAO should always exist
4121 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004122 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004123 return false;
4124 }
4125
4126 return true;
4127}
4128
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004129bool ValidateLinkProgram(Context *context, GLuint program)
4130{
4131 if (context->hasActiveTransformFeedback(program))
4132 {
4133 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004134 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004135 "Cannot link program while program is associated with an active "
4136 "transform feedback object."));
4137 return false;
4138 }
4139 return true;
4140}
4141
Geoff Langc5629752015-12-07 16:29:04 -05004142bool ValidateProgramBinaryBase(Context *context,
4143 GLuint program,
4144 GLenum binaryFormat,
4145 const void *binary,
4146 GLint length)
4147{
4148 Program *programObject = GetValidProgram(context, program);
4149 if (programObject == nullptr)
4150 {
4151 return false;
4152 }
4153
4154 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4155 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4156 programBinaryFormats.end())
4157 {
Jamie Madill437fa652016-05-03 15:13:24 -04004158 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004159 return false;
4160 }
4161
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004162 if (context->hasActiveTransformFeedback(program))
4163 {
4164 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004165 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004166 "Cannot change program binary while program is associated with "
4167 "an active transform feedback object."));
4168 return false;
4169 }
4170
Geoff Langc5629752015-12-07 16:29:04 -05004171 return true;
4172}
4173
4174bool ValidateGetProgramBinaryBase(Context *context,
4175 GLuint program,
4176 GLsizei bufSize,
4177 GLsizei *length,
4178 GLenum *binaryFormat,
4179 void *binary)
4180{
4181 Program *programObject = GetValidProgram(context, program);
4182 if (programObject == nullptr)
4183 {
4184 return false;
4185 }
4186
4187 if (!programObject->isLinked())
4188 {
Jamie Madill437fa652016-05-03 15:13:24 -04004189 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004190 return false;
4191 }
4192
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004193 if (context->getCaps().programBinaryFormats.empty())
4194 {
4195 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4196 return false;
4197 }
4198
Geoff Langc5629752015-12-07 16:29:04 -05004199 return true;
4200}
Jamie Madillc29968b2016-01-20 11:17:23 -05004201
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004202bool ValidateUseProgram(Context *context, GLuint program)
4203{
4204 if (program != 0)
4205 {
4206 Program *programObject = context->getProgram(program);
4207 if (!programObject)
4208 {
4209 // ES 3.1.0 section 7.3 page 72
4210 if (context->getShader(program))
4211 {
Jamie Madill437fa652016-05-03 15:13:24 -04004212 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004213 Error(GL_INVALID_OPERATION,
4214 "Attempted to use a single shader instead of a shader program."));
4215 return false;
4216 }
4217 else
4218 {
Jamie Madill437fa652016-05-03 15:13:24 -04004219 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004220 return false;
4221 }
4222 }
4223 if (!programObject->isLinked())
4224 {
Jamie Madill437fa652016-05-03 15:13:24 -04004225 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004226 return false;
4227 }
4228 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004229 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004230 {
4231 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004232 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004233 Error(GL_INVALID_OPERATION,
4234 "Cannot change active program while transform feedback is unpaused."));
4235 return false;
4236 }
4237
4238 return true;
4239}
4240
Jamie Madillc29968b2016-01-20 11:17:23 -05004241bool ValidateCopyTexImage2D(ValidationContext *context,
4242 GLenum target,
4243 GLint level,
4244 GLenum internalformat,
4245 GLint x,
4246 GLint y,
4247 GLsizei width,
4248 GLsizei height,
4249 GLint border)
4250{
Martin Radev1be913c2016-07-11 17:59:16 +03004251 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004252 {
4253 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4254 0, x, y, width, height, border);
4255 }
4256
Martin Radev1be913c2016-07-11 17:59:16 +03004257 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004258 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4259 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004260}
Jamie Madillc29968b2016-01-20 11:17:23 -05004261
4262bool ValidateFramebufferRenderbuffer(Context *context,
4263 GLenum target,
4264 GLenum attachment,
4265 GLenum renderbuffertarget,
4266 GLuint renderbuffer)
4267{
4268 if (!ValidFramebufferTarget(target) ||
4269 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4270 {
Jamie Madill437fa652016-05-03 15:13:24 -04004271 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004272 return false;
4273 }
4274
4275 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4276 renderbuffertarget, renderbuffer);
4277}
4278
4279bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4280{
4281 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4282 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4283 {
Jamie Madill437fa652016-05-03 15:13:24 -04004284 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004285 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4286 return false;
4287 }
4288
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004289 ASSERT(context->getGLState().getDrawFramebuffer());
4290 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004291 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4292
4293 // This should come first before the check for the default frame buffer
4294 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4295 // rather than INVALID_OPERATION
4296 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4297 {
4298 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4299
4300 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004301 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4302 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004303 {
4304 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004305 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4306 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4307 // 3.1 is still a bit ambiguous about the error, but future specs are
4308 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004309 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004310 return false;
4311 }
4312 else if (bufs[colorAttachment] >= maxColorAttachment)
4313 {
Jamie Madill437fa652016-05-03 15:13:24 -04004314 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004315 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004316 return false;
4317 }
4318 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4319 frameBufferId != 0)
4320 {
4321 // INVALID_OPERATION-GL is bound to buffer and ith argument
4322 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004323 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004324 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4325 return false;
4326 }
4327 }
4328
4329 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4330 // and n is not 1 or bufs is bound to value other than BACK and NONE
4331 if (frameBufferId == 0)
4332 {
4333 if (n != 1)
4334 {
Jamie Madill437fa652016-05-03 15:13:24 -04004335 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004336 "n must be 1 when GL is bound to the default framebuffer"));
4337 return false;
4338 }
4339
4340 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4341 {
Jamie Madill437fa652016-05-03 15:13:24 -04004342 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004343 GL_INVALID_OPERATION,
4344 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4345 return false;
4346 }
4347 }
4348
4349 return true;
4350}
4351
4352bool ValidateCopyTexSubImage2D(Context *context,
4353 GLenum target,
4354 GLint level,
4355 GLint xoffset,
4356 GLint yoffset,
4357 GLint x,
4358 GLint y,
4359 GLsizei width,
4360 GLsizei height)
4361{
Martin Radev1be913c2016-07-11 17:59:16 +03004362 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004363 {
4364 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4365 yoffset, x, y, width, height, 0);
4366 }
4367
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004368 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4369 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004370}
4371
Geoff Lang496c02d2016-10-20 11:38:11 -07004372bool ValidateGetBufferPointervBase(Context *context,
4373 GLenum target,
4374 GLenum pname,
4375 GLsizei *length,
4376 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004377{
Geoff Lang496c02d2016-10-20 11:38:11 -07004378 if (length)
4379 {
4380 *length = 0;
4381 }
4382
4383 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4384 {
4385 context->handleError(
4386 Error(GL_INVALID_OPERATION,
Jamie Madillcc6ac252017-01-25 12:57:21 -08004387 "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled."));
Geoff Lang496c02d2016-10-20 11:38:11 -07004388 return false;
4389 }
4390
Olli Etuaho4f667482016-03-30 15:56:35 +03004391 if (!ValidBufferTarget(context, target))
4392 {
Jamie Madill437fa652016-05-03 15:13:24 -04004393 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004394 return false;
4395 }
4396
Geoff Lang496c02d2016-10-20 11:38:11 -07004397 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004398 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004399 case GL_BUFFER_MAP_POINTER:
4400 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004401
Geoff Lang496c02d2016-10-20 11:38:11 -07004402 default:
4403 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4404 return false;
4405 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004406
4407 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4408 // target bound to zero generate an INVALID_OPERATION error."
4409 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004410 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004411 {
Jamie Madill437fa652016-05-03 15:13:24 -04004412 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004413 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4414 return false;
4415 }
4416
Geoff Lang496c02d2016-10-20 11:38:11 -07004417 if (length)
4418 {
4419 *length = 1;
4420 }
4421
Olli Etuaho4f667482016-03-30 15:56:35 +03004422 return true;
4423}
4424
4425bool ValidateUnmapBufferBase(Context *context, GLenum target)
4426{
4427 if (!ValidBufferTarget(context, target))
4428 {
Jamie Madill437fa652016-05-03 15:13:24 -04004429 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004430 return false;
4431 }
4432
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004433 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004434
4435 if (buffer == nullptr || !buffer->isMapped())
4436 {
Jamie Madill437fa652016-05-03 15:13:24 -04004437 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004438 return false;
4439 }
4440
4441 return true;
4442}
4443
4444bool ValidateMapBufferRangeBase(Context *context,
4445 GLenum target,
4446 GLintptr offset,
4447 GLsizeiptr length,
4448 GLbitfield access)
4449{
4450 if (!ValidBufferTarget(context, target))
4451 {
Jamie Madill437fa652016-05-03 15:13:24 -04004452 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004453 return false;
4454 }
4455
4456 if (offset < 0 || length < 0)
4457 {
Jamie Madill437fa652016-05-03 15:13:24 -04004458 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
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)
4465 {
Jamie Madill437fa652016-05-03 15:13:24 -04004466 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004467 return false;
4468 }
4469
4470 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004471 CheckedNumeric<size_t> checkedOffset(offset);
4472 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004473
Jamie Madille2e406c2016-06-02 13:04:10 -04004474 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004475 {
Jamie Madill437fa652016-05-03 15:13:24 -04004476 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004477 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4478 return false;
4479 }
4480
4481 // Check for invalid bits in the mask
4482 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4483 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4484 GL_MAP_UNSYNCHRONIZED_BIT;
4485
4486 if (access & ~(allAccessBits))
4487 {
Jamie Madill437fa652016-05-03 15:13:24 -04004488 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004489 return false;
4490 }
4491
4492 if (length == 0)
4493 {
Jamie Madill437fa652016-05-03 15:13:24 -04004494 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004495 return false;
4496 }
4497
4498 if (buffer->isMapped())
4499 {
Jamie Madill437fa652016-05-03 15:13:24 -04004500 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004501 return false;
4502 }
4503
4504 // Check for invalid bit combinations
4505 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4506 {
Jamie Madill437fa652016-05-03 15:13:24 -04004507 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004508 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4509 return false;
4510 }
4511
4512 GLbitfield writeOnlyBits =
4513 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4514
4515 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4516 {
Jamie Madill437fa652016-05-03 15:13:24 -04004517 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004518 "Invalid access bits when mapping buffer for reading: 0x%X.",
4519 access));
4520 return false;
4521 }
4522
4523 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4524 {
Jamie Madill437fa652016-05-03 15:13:24 -04004525 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004526 GL_INVALID_OPERATION,
4527 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4528 return false;
4529 }
4530 return true;
4531}
4532
4533bool ValidateFlushMappedBufferRangeBase(Context *context,
4534 GLenum target,
4535 GLintptr offset,
4536 GLsizeiptr length)
4537{
4538 if (offset < 0 || length < 0)
4539 {
Jamie Madill437fa652016-05-03 15:13:24 -04004540 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004541 return false;
4542 }
4543
4544 if (!ValidBufferTarget(context, target))
4545 {
Jamie Madill437fa652016-05-03 15:13:24 -04004546 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004547 return false;
4548 }
4549
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004550 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004551
4552 if (buffer == nullptr)
4553 {
Jamie Madill437fa652016-05-03 15:13:24 -04004554 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004555 return false;
4556 }
4557
4558 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4559 {
Jamie Madill437fa652016-05-03 15:13:24 -04004560 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004561 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4562 return false;
4563 }
4564
4565 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004566 CheckedNumeric<size_t> checkedOffset(offset);
4567 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004568
Jamie Madille2e406c2016-06-02 13:04:10 -04004569 if (!checkedSize.IsValid() ||
4570 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004571 {
Jamie Madill437fa652016-05-03 15:13:24 -04004572 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004573 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4574 return false;
4575 }
4576
4577 return true;
4578}
4579
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004580bool ValidateGenerateMipmap(Context *context, GLenum target)
4581{
4582 if (!ValidTextureTarget(context, target))
4583 {
4584 context->handleError(Error(GL_INVALID_ENUM));
4585 return false;
4586 }
4587
4588 Texture *texture = context->getTargetTexture(target);
4589
4590 if (texture == nullptr)
4591 {
4592 context->handleError(Error(GL_INVALID_OPERATION));
4593 return false;
4594 }
4595
4596 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4597
4598 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4599 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4600 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4601 {
4602 context->handleError(Error(GL_INVALID_OPERATION));
4603 return false;
4604 }
4605
Jamie Madilla3944d42016-07-22 22:13:26 -04004606 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4607 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4608 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004609
4610 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4611 // unsized formats or that are color renderable and filterable. Since we do not track if
4612 // the texture was created with sized or unsized format (only sized formats are stored),
4613 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4614 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4615 // textures since they're the only texture format that can be created with unsized formats
4616 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4617 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004618 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4619 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004620 {
4621 context->handleError(Error(GL_INVALID_OPERATION));
4622 return false;
4623 }
4624
4625 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004626 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004627 {
4628 context->handleError(Error(GL_INVALID_OPERATION));
4629 return false;
4630 }
4631
4632 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004633 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004634 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4635 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4636 {
Geoff Lang55482a12016-11-21 16:54:01 -05004637 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004638 context->handleError(Error(GL_INVALID_OPERATION));
4639 return false;
4640 }
4641
4642 // Cube completeness check
4643 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4644 {
4645 context->handleError(Error(GL_INVALID_OPERATION));
4646 return false;
4647 }
4648
4649 return true;
4650}
4651
Olli Etuaho41997e72016-03-10 13:38:39 +02004652bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4653{
4654 return ValidateGenOrDelete(context, n);
4655}
4656
4657bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4658{
4659 return ValidateGenOrDelete(context, n);
4660}
4661
4662bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4663{
4664 return ValidateGenOrDelete(context, n);
4665}
4666
4667bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4668{
4669 return ValidateGenOrDelete(context, n);
4670}
4671
4672bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4673{
4674 return ValidateGenOrDelete(context, n);
4675}
4676
4677bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4678{
4679 return ValidateGenOrDelete(context, n);
4680}
4681
4682bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4683{
4684 return ValidateGenOrDelete(context, n);
4685}
4686
4687bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4688{
4689 return ValidateGenOrDelete(context, n);
4690}
4691
4692bool ValidateGenOrDelete(Context *context, GLint n)
4693{
4694 if (n < 0)
4695 {
Jamie Madill437fa652016-05-03 15:13:24 -04004696 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004697 return false;
4698 }
4699 return true;
4700}
4701
Geoff Langf41a7152016-09-19 15:11:17 -04004702bool ValidateEnable(Context *context, GLenum cap)
4703{
4704 if (!ValidCap(context, cap, false))
4705 {
4706 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4707 return false;
4708 }
4709
4710 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4711 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4712 {
4713 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4714 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4715
4716 // We also output an error message to the debugger window if tracing is active, so that
4717 // developers can see the error message.
Yuly Novikovd73f8522017-01-13 17:48:57 -05004718 ERR() << errorMessage;
Geoff Langf41a7152016-09-19 15:11:17 -04004719 return false;
4720 }
4721
4722 return true;
4723}
4724
4725bool ValidateDisable(Context *context, GLenum cap)
4726{
4727 if (!ValidCap(context, cap, false))
4728 {
4729 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4730 return false;
4731 }
4732
4733 return true;
4734}
4735
4736bool ValidateIsEnabled(Context *context, GLenum cap)
4737{
4738 if (!ValidCap(context, cap, true))
4739 {
4740 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4741 return false;
4742 }
4743
4744 return true;
4745}
4746
Geoff Langff5b2d52016-09-07 11:32:23 -04004747bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4748{
4749 if (!context->getExtensions().robustClientMemory)
4750 {
4751 context->handleError(
4752 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4753 return false;
4754 }
4755
4756 if (bufSize < 0)
4757 {
4758 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4759 return false;
4760 }
4761
4762 return true;
4763}
4764
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004765bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4766{
4767 if (bufSize < numParams)
4768 {
4769 context->handleError(Error(GL_INVALID_OPERATION,
4770 "%u parameters are required but %i were provided.", numParams,
4771 bufSize));
4772 return false;
4773 }
4774
4775 return true;
4776}
4777
Geoff Langff5b2d52016-09-07 11:32:23 -04004778bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4779 GLenum target,
4780 GLenum attachment,
4781 GLenum pname,
4782 GLsizei *numParams)
4783{
4784 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4785 *numParams = 1;
4786
4787 if (!ValidFramebufferTarget(target))
4788 {
4789 context->handleError(Error(GL_INVALID_ENUM));
4790 return false;
4791 }
4792
4793 int clientVersion = context->getClientMajorVersion();
4794
4795 switch (pname)
4796 {
4797 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4798 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4799 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4800 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4801 break;
4802
4803 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4804 if (clientVersion < 3 && !context->getExtensions().sRGB)
4805 {
4806 context->handleError(Error(GL_INVALID_ENUM));
4807 return false;
4808 }
4809 break;
4810
4811 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4812 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4813 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4814 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4815 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4816 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4817 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4818 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4819 if (clientVersion < 3)
4820 {
4821 context->handleError(Error(GL_INVALID_ENUM));
4822 return false;
4823 }
4824 break;
4825
4826 default:
4827 context->handleError(Error(GL_INVALID_ENUM));
4828 return false;
4829 }
4830
4831 // Determine if the attachment is a valid enum
4832 switch (attachment)
4833 {
4834 case GL_BACK:
4835 case GL_FRONT:
4836 case GL_DEPTH:
4837 case GL_STENCIL:
4838 case GL_DEPTH_STENCIL_ATTACHMENT:
4839 if (clientVersion < 3)
4840 {
4841 context->handleError(Error(GL_INVALID_ENUM));
4842 return false;
4843 }
4844 break;
4845
4846 case GL_DEPTH_ATTACHMENT:
4847 case GL_STENCIL_ATTACHMENT:
4848 break;
4849
4850 default:
4851 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4852 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4853 {
4854 context->handleError(Error(GL_INVALID_ENUM));
4855 return false;
4856 }
4857 break;
4858 }
4859
4860 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4861 ASSERT(framebuffer);
4862
4863 if (framebuffer->id() == 0)
4864 {
4865 if (clientVersion < 3)
4866 {
4867 context->handleError(Error(GL_INVALID_OPERATION));
4868 return false;
4869 }
4870
4871 switch (attachment)
4872 {
4873 case GL_BACK:
4874 case GL_DEPTH:
4875 case GL_STENCIL:
4876 break;
4877
4878 default:
4879 context->handleError(Error(GL_INVALID_OPERATION));
4880 return false;
4881 }
4882 }
4883 else
4884 {
4885 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4886 {
4887 // Valid attachment query
4888 }
4889 else
4890 {
4891 switch (attachment)
4892 {
4893 case GL_DEPTH_ATTACHMENT:
4894 case GL_STENCIL_ATTACHMENT:
4895 break;
4896
4897 case GL_DEPTH_STENCIL_ATTACHMENT:
4898 if (!framebuffer->hasValidDepthStencil())
4899 {
4900 context->handleError(Error(GL_INVALID_OPERATION));
4901 return false;
4902 }
4903 break;
4904
4905 default:
4906 context->handleError(Error(GL_INVALID_OPERATION));
4907 return false;
4908 }
4909 }
4910 }
4911
4912 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4913 if (attachmentObject)
4914 {
4915 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4916 attachmentObject->type() == GL_TEXTURE ||
4917 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4918
4919 switch (pname)
4920 {
4921 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4922 if (attachmentObject->type() != GL_RENDERBUFFER &&
4923 attachmentObject->type() != GL_TEXTURE)
4924 {
4925 context->handleError(Error(GL_INVALID_ENUM));
4926 return false;
4927 }
4928 break;
4929
4930 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4931 if (attachmentObject->type() != GL_TEXTURE)
4932 {
4933 context->handleError(Error(GL_INVALID_ENUM));
4934 return false;
4935 }
4936 break;
4937
4938 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4939 if (attachmentObject->type() != GL_TEXTURE)
4940 {
4941 context->handleError(Error(GL_INVALID_ENUM));
4942 return false;
4943 }
4944 break;
4945
4946 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4947 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4948 {
4949 context->handleError(Error(GL_INVALID_OPERATION));
4950 return false;
4951 }
4952 break;
4953
4954 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4955 if (attachmentObject->type() != GL_TEXTURE)
4956 {
4957 context->handleError(Error(GL_INVALID_ENUM));
4958 return false;
4959 }
4960 break;
4961
4962 default:
4963 break;
4964 }
4965 }
4966 else
4967 {
4968 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4969 // is NONE, then querying any other pname will generate INVALID_ENUM.
4970
4971 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4972 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4973 // INVALID_OPERATION for all other pnames
4974
4975 switch (pname)
4976 {
4977 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4978 break;
4979
4980 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4981 if (clientVersion < 3)
4982 {
4983 context->handleError(Error(GL_INVALID_ENUM));
4984 return false;
4985 }
4986 break;
4987
4988 default:
4989 if (clientVersion < 3)
4990 {
4991 context->handleError(Error(GL_INVALID_ENUM));
4992 return false;
4993 }
4994 else
4995 {
4996 context->handleError(Error(GL_INVALID_OPERATION));
4997 return false;
4998 }
4999 }
5000 }
5001
5002 return true;
5003}
5004
5005bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
5006 GLenum target,
5007 GLenum attachment,
5008 GLenum pname,
5009 GLsizei bufSize,
5010 GLsizei *numParams)
5011{
5012 if (!ValidateRobustEntryPoint(context, bufSize))
5013 {
5014 return false;
5015 }
5016
5017 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
5018 {
5019 return false;
5020 }
5021
5022 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5023 {
5024 return false;
5025 }
5026
5027 return true;
5028}
5029
5030bool ValidateGetBufferParameteriv(ValidationContext *context,
5031 GLenum target,
5032 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04005033 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005034{
Geoff Langebebe1c2016-10-14 12:01:31 -04005035 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04005036}
5037
5038bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
5039 GLenum target,
5040 GLenum pname,
5041 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04005042 GLsizei *length,
5043 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04005044{
5045 if (!ValidateRobustEntryPoint(context, bufSize))
5046 {
5047 return false;
5048 }
5049
Geoff Langebebe1c2016-10-14 12:01:31 -04005050 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005051 {
5052 return false;
5053 }
5054
Geoff Langebebe1c2016-10-14 12:01:31 -04005055 if (!ValidateRobustBufferSize(context, bufSize, *length))
5056 {
5057 return false;
5058 }
5059
5060 return true;
5061}
5062
5063bool ValidateGetBufferParameteri64v(ValidationContext *context,
5064 GLenum target,
5065 GLenum pname,
5066 GLint64 *params)
5067{
5068 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5069}
5070
5071bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5072 GLenum target,
5073 GLenum pname,
5074 GLsizei bufSize,
5075 GLsizei *length,
5076 GLint64 *params)
5077{
5078 if (!ValidateRobustEntryPoint(context, bufSize))
5079 {
5080 return false;
5081 }
5082
5083 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5084 {
5085 return false;
5086 }
5087
5088 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005089 {
5090 return false;
5091 }
5092
5093 return true;
5094}
5095
5096bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5097{
5098 // Currently, all GetProgramiv queries return 1 parameter
5099 *numParams = 1;
5100
5101 Program *programObject = GetValidProgram(context, program);
5102 if (!programObject)
5103 {
5104 return false;
5105 }
5106
5107 switch (pname)
5108 {
5109 case GL_DELETE_STATUS:
5110 case GL_LINK_STATUS:
5111 case GL_VALIDATE_STATUS:
5112 case GL_INFO_LOG_LENGTH:
5113 case GL_ATTACHED_SHADERS:
5114 case GL_ACTIVE_ATTRIBUTES:
5115 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5116 case GL_ACTIVE_UNIFORMS:
5117 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5118 break;
5119
5120 case GL_PROGRAM_BINARY_LENGTH:
5121 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5122 {
5123 context->handleError(Error(GL_INVALID_ENUM,
5124 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5125 "GL_OES_get_program_binary or ES 3.0."));
5126 return false;
5127 }
5128 break;
5129
5130 case GL_ACTIVE_UNIFORM_BLOCKS:
5131 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5132 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5133 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5134 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5135 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5136 if (context->getClientMajorVersion() < 3)
5137 {
5138 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5139 return false;
5140 }
5141 break;
5142
5143 default:
5144 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5145 return false;
5146 }
5147
5148 return true;
5149}
5150
5151bool ValidateGetProgramivRobustANGLE(Context *context,
5152 GLuint program,
5153 GLenum pname,
5154 GLsizei bufSize,
5155 GLsizei *numParams)
5156{
5157 if (!ValidateRobustEntryPoint(context, bufSize))
5158 {
5159 return false;
5160 }
5161
5162 if (!ValidateGetProgramiv(context, program, pname, numParams))
5163 {
5164 return false;
5165 }
5166
5167 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5168 {
5169 return false;
5170 }
5171
5172 return true;
5173}
5174
Geoff Lang740d9022016-10-07 11:20:52 -04005175bool ValidateGetRenderbufferParameteriv(Context *context,
5176 GLenum target,
5177 GLenum pname,
5178 GLint *params)
5179{
5180 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5181}
5182
5183bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5184 GLenum target,
5185 GLenum pname,
5186 GLsizei bufSize,
5187 GLsizei *length,
5188 GLint *params)
5189{
5190 if (!ValidateRobustEntryPoint(context, bufSize))
5191 {
5192 return false;
5193 }
5194
5195 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5196 {
5197 return false;
5198 }
5199
5200 if (!ValidateRobustBufferSize(context, bufSize, *length))
5201 {
5202 return false;
5203 }
5204
5205 return true;
5206}
5207
Geoff Langd7d0ed32016-10-07 11:33:51 -04005208bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5209{
5210 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5211}
5212
5213bool ValidateGetShaderivRobustANGLE(Context *context,
5214 GLuint shader,
5215 GLenum pname,
5216 GLsizei bufSize,
5217 GLsizei *length,
5218 GLint *params)
5219{
5220 if (!ValidateRobustEntryPoint(context, bufSize))
5221 {
5222 return false;
5223 }
5224
5225 if (!ValidateGetShaderivBase(context, shader, pname, length))
5226 {
5227 return false;
5228 }
5229
5230 if (!ValidateRobustBufferSize(context, bufSize, *length))
5231 {
5232 return false;
5233 }
5234
5235 return true;
5236}
5237
Geoff Langc1984ed2016-10-07 12:41:00 -04005238bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5239{
5240 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5241}
5242
5243bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5244 GLenum target,
5245 GLenum pname,
5246 GLsizei bufSize,
5247 GLsizei *length,
5248 GLfloat *params)
5249{
5250 if (!ValidateRobustEntryPoint(context, bufSize))
5251 {
5252 return false;
5253 }
5254
5255 if (!ValidateGetTexParameterBase(context, target, pname, length))
5256 {
5257 return false;
5258 }
5259
5260 if (!ValidateRobustBufferSize(context, bufSize, *length))
5261 {
5262 return false;
5263 }
5264
5265 return true;
5266}
5267
5268bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5269{
5270 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5271}
5272
5273bool ValidateGetTexParameterivRobustANGLE(Context *context,
5274 GLenum target,
5275 GLenum pname,
5276 GLsizei bufSize,
5277 GLsizei *length,
5278 GLint *params)
5279{
5280 if (!ValidateRobustEntryPoint(context, bufSize))
5281 {
5282 return false;
5283 }
5284
5285 if (!ValidateGetTexParameterBase(context, target, pname, length))
5286 {
5287 return false;
5288 }
5289
5290 if (!ValidateRobustBufferSize(context, bufSize, *length))
5291 {
5292 return false;
5293 }
5294
5295 return true;
5296}
5297
5298bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5299{
5300 return ValidateTexParameterBase(context, target, pname, -1, &param);
5301}
5302
5303bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5304{
5305 return ValidateTexParameterBase(context, target, pname, -1, params);
5306}
5307
5308bool ValidateTexParameterfvRobustANGLE(Context *context,
5309 GLenum target,
5310 GLenum pname,
5311 GLsizei bufSize,
5312 const GLfloat *params)
5313{
5314 if (!ValidateRobustEntryPoint(context, bufSize))
5315 {
5316 return false;
5317 }
5318
5319 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5320}
5321
5322bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5323{
5324 return ValidateTexParameterBase(context, target, pname, -1, &param);
5325}
5326
5327bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5328{
5329 return ValidateTexParameterBase(context, target, pname, -1, params);
5330}
5331
5332bool ValidateTexParameterivRobustANGLE(Context *context,
5333 GLenum target,
5334 GLenum pname,
5335 GLsizei bufSize,
5336 const GLint *params)
5337{
5338 if (!ValidateRobustEntryPoint(context, bufSize))
5339 {
5340 return false;
5341 }
5342
5343 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5344}
5345
5346bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5347{
5348 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5349}
5350
5351bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5352 GLuint sampler,
5353 GLenum pname,
5354 GLuint bufSize,
5355 GLsizei *length,
5356 GLfloat *params)
5357{
5358 if (!ValidateRobustEntryPoint(context, bufSize))
5359 {
5360 return false;
5361 }
5362
5363 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5364 {
5365 return false;
5366 }
5367
5368 if (!ValidateRobustBufferSize(context, bufSize, *length))
5369 {
5370 return false;
5371 }
5372
5373 return true;
5374}
5375
5376bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5377{
5378 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5379}
5380
5381bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5382 GLuint sampler,
5383 GLenum pname,
5384 GLuint bufSize,
5385 GLsizei *length,
5386 GLint *params)
5387{
5388 if (!ValidateRobustEntryPoint(context, bufSize))
5389 {
5390 return false;
5391 }
5392
5393 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5394 {
5395 return false;
5396 }
5397
5398 if (!ValidateRobustBufferSize(context, bufSize, *length))
5399 {
5400 return false;
5401 }
5402
5403 return true;
5404}
5405
5406bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5407{
5408 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5409}
5410
5411bool ValidateSamplerParameterfv(Context *context,
5412 GLuint sampler,
5413 GLenum pname,
5414 const GLfloat *params)
5415{
5416 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5417}
5418
5419bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5420 GLuint sampler,
5421 GLenum pname,
5422 GLsizei bufSize,
5423 const GLfloat *params)
5424{
5425 if (!ValidateRobustEntryPoint(context, bufSize))
5426 {
5427 return false;
5428 }
5429
5430 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5431}
5432
5433bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5434{
5435 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5436}
5437
5438bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5439{
5440 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5441}
5442
5443bool ValidateSamplerParameterivRobustANGLE(Context *context,
5444 GLuint sampler,
5445 GLenum pname,
5446 GLsizei bufSize,
5447 const GLint *params)
5448{
5449 if (!ValidateRobustEntryPoint(context, bufSize))
5450 {
5451 return false;
5452 }
5453
5454 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5455}
5456
Geoff Lang0b031062016-10-13 14:30:04 -04005457bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5458{
5459 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5460}
5461
5462bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5463 GLuint index,
5464 GLenum pname,
5465 GLsizei bufSize,
5466 GLsizei *length,
5467 GLfloat *params)
5468{
5469 if (!ValidateRobustEntryPoint(context, bufSize))
5470 {
5471 return false;
5472 }
5473
5474 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5475 {
5476 return false;
5477 }
5478
5479 if (!ValidateRobustBufferSize(context, bufSize, *length))
5480 {
5481 return false;
5482 }
5483
5484 return true;
5485}
5486
5487bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5488{
5489 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5490}
5491
5492bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5493 GLuint index,
5494 GLenum pname,
5495 GLsizei bufSize,
5496 GLsizei *length,
5497 GLint *params)
5498{
5499 if (!ValidateRobustEntryPoint(context, bufSize))
5500 {
5501 return false;
5502 }
5503
5504 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5505 {
5506 return false;
5507 }
5508
5509 if (!ValidateRobustBufferSize(context, bufSize, *length))
5510 {
5511 return false;
5512 }
5513
5514 return true;
5515}
5516
5517bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5518{
5519 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5520}
5521
5522bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5523 GLuint index,
5524 GLenum pname,
5525 GLsizei bufSize,
5526 GLsizei *length,
5527 void **pointer)
5528{
5529 if (!ValidateRobustEntryPoint(context, bufSize))
5530 {
5531 return false;
5532 }
5533
5534 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5535 {
5536 return false;
5537 }
5538
5539 if (!ValidateRobustBufferSize(context, bufSize, *length))
5540 {
5541 return false;
5542 }
5543
5544 return true;
5545}
5546
5547bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5548{
5549 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5550}
5551
5552bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5553 GLuint index,
5554 GLenum pname,
5555 GLsizei bufSize,
5556 GLsizei *length,
5557 GLint *params)
5558{
5559 if (!ValidateRobustEntryPoint(context, bufSize))
5560 {
5561 return false;
5562 }
5563
5564 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5565 {
5566 return false;
5567 }
5568
5569 if (!ValidateRobustBufferSize(context, bufSize, *length))
5570 {
5571 return false;
5572 }
5573
5574 return true;
5575}
5576
5577bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5578{
5579 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5580}
5581
5582bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5583 GLuint index,
5584 GLenum pname,
5585 GLsizei bufSize,
5586 GLsizei *length,
5587 GLuint *params)
5588{
5589 if (!ValidateRobustEntryPoint(context, bufSize))
5590 {
5591 return false;
5592 }
5593
5594 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5595 {
5596 return false;
5597 }
5598
5599 if (!ValidateRobustBufferSize(context, bufSize, *length))
5600 {
5601 return false;
5602 }
5603
5604 return true;
5605}
5606
Geoff Lang6899b872016-10-14 11:30:13 -04005607bool ValidateGetActiveUniformBlockiv(Context *context,
5608 GLuint program,
5609 GLuint uniformBlockIndex,
5610 GLenum pname,
5611 GLint *params)
5612{
5613 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5614}
5615
5616bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5617 GLuint program,
5618 GLuint uniformBlockIndex,
5619 GLenum pname,
5620 GLsizei bufSize,
5621 GLsizei *length,
5622 GLint *params)
5623{
5624 if (!ValidateRobustEntryPoint(context, bufSize))
5625 {
5626 return false;
5627 }
5628
5629 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5630 {
5631 return false;
5632 }
5633
5634 if (!ValidateRobustBufferSize(context, bufSize, *length))
5635 {
5636 return false;
5637 }
5638
5639 return true;
5640}
5641
Geoff Lang0a9661f2016-10-20 10:59:20 -07005642bool ValidateGetInternalFormativ(Context *context,
5643 GLenum target,
5644 GLenum internalformat,
5645 GLenum pname,
5646 GLsizei bufSize,
5647 GLint *params)
5648{
5649 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5650 nullptr);
5651}
5652
5653bool ValidateGetInternalFormativRobustANGLE(Context *context,
5654 GLenum target,
5655 GLenum internalformat,
5656 GLenum pname,
5657 GLsizei bufSize,
5658 GLsizei *length,
5659 GLint *params)
5660{
5661 if (!ValidateRobustEntryPoint(context, bufSize))
5662 {
5663 return false;
5664 }
5665
5666 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5667 {
5668 return false;
5669 }
5670
5671 if (!ValidateRobustBufferSize(context, bufSize, *length))
5672 {
5673 return false;
5674 }
5675
5676 return true;
5677}
5678
Jamie Madillc29968b2016-01-20 11:17:23 -05005679} // namespace gl