blob: 5baf1918fc0dabb9bb2e2b834fa57cde1e83cfd3 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/validationES2.h"
12#include "libANGLE/validationES3.h"
13#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040014#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Texture.h"
16#include "libANGLE/Framebuffer.h"
17#include "libANGLE/FramebufferAttachment.h"
18#include "libANGLE/formatutils.h"
Geoff Langa8406172015-07-21 16:53:39 -040019#include "libANGLE/Image.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/Query.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050021#include "libANGLE/Program.h"
22#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/TransformFeedback.h"
24#include "libANGLE/VertexArray.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040025
26#include "common/mathutil.h"
27#include "common/utilities.h"
28
Jamie Madille2e406c2016-06-02 13:04:10 -040029using namespace angle;
30
Geoff Lange8ebe7f2013-08-05 15:03:13 -040031namespace gl
32{
Jamie Madille79b1e12015-11-04 16:36:37 -050033const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index.";
34
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Corentin Wallez92db6942016-12-09 13:10:36 -050037bool ValidateDrawAttribs(ValidationContext *context,
38 GLint primcount,
39 GLint maxVertex,
40 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040041{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070042 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040043 const gl::Program *program = state.getProgram();
44
Corentin Wallez327411e2016-12-09 11:09:17 -050045 bool webglCompatibility = context->getExtensions().webglCompatibility;
46
He Yunchaoced53ae2016-11-29 15:00:51 +080047 const VertexArray *vao = state.getVertexArray();
48 const auto &vertexAttribs = vao->getVertexAttributes();
49 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040050 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
51 {
52 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallezfd456442016-12-21 17:57:00 -050053 if (!program->isAttribLocationActive(attributeIndex) || !attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040054 {
Corentin Wallezfd456442016-12-21 17:57:00 -050055 continue;
56 }
Jamie Madill1ca74672015-07-21 15:14:11 -040057
Corentin Wallezfd456442016-12-21 17:57:00 -050058 // If we have no buffer, then we either get an error, or there are no more checks to be done.
59 gl::Buffer *buffer = attrib.buffer.get();
60 if (!buffer)
61 {
62 if (webglCompatibility)
Corentin Wallez327411e2016-12-09 11:09:17 -050063 {
64 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050065 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
66 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
67 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
68 // error.
Corentin Wallez327411e2016-12-09 11:09:17 -050069 context->handleError(
70 Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer."));
Corentin Wallezfd456442016-12-21 17:57:00 -050071 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050072 }
Corentin Wallezfd456442016-12-21 17:57:00 -050073 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040074 {
75 // This is an application error that would normally result in a crash,
76 // but we catch it and return an error
Corentin Wallezfd456442016-12-21 17:57:00 -050077 context->handleError(
78 Error(GL_INVALID_OPERATION,
79 "An enabled vertex array has no buffer and no pointer."));
Jamie Madill1ca74672015-07-21 15:14:11 -040080 return false;
81 }
Corentin Wallezfd456442016-12-21 17:57:00 -050082 continue;
83 }
84
85 // If we're drawing zero vertices, we have enough data.
86 if (vertexCount <= 0 || primcount <= 0)
87 {
88 continue;
89 }
90
91 GLint maxVertexElement = 0;
92 if (attrib.divisor == 0)
93 {
94 maxVertexElement = maxVertex;
95 }
96 else
97 {
98 maxVertexElement = (primcount - 1) / attrib.divisor;
99 }
100
101 // We do manual overflow checks here instead of using safe_math.h because it was
102 // a bottleneck. Thanks to some properties of GL we know inequalities that can
103 // help us make the overflow checks faster.
104
105 // The max possible attribSize is 16 for a vector of 4 32 bit values.
106 constexpr uint64_t kMaxAttribSize = 16;
107 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
108 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
109
110 // We know attribStride is given as a GLsizei which is typedefed to int.
111 // We also know an upper bound for attribSize.
112 static_assert(std::is_same<int, GLsizei>::value, "");
113 uint64_t attribStride = ComputeVertexAttributeStride(attrib);
114 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
115 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
116
117 // Computing the max offset using uint64_t without attrib.offset is overflow
118 // safe. Note: Last vertex element does not take the full stride!
119 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
120 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
121
122 // An overflow can happen when adding the offset, check for it.
123 uint64_t attribOffset = attrib.offset;
124 if (attribDataSizeNoOffset > kUint64Max - attrib.offset)
125 {
126 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
127 return false;
128 }
129 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
130
131 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
132 // We can return INVALID_OPERATION if our vertex attribute does not have
133 // enough backing data.
134 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
135 {
136 context->handleError(Error(GL_INVALID_OPERATION,
137 "Vertex buffer is not big enough for the draw call"));
138 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400139 }
140 }
141
142 return true;
143}
144
Geoff Langf607c602016-09-21 11:46:48 -0400145bool ValidReadPixelsFormatType(ValidationContext *context,
146 GLenum framebufferComponentType,
147 GLenum format,
148 GLenum type)
149{
150 switch (framebufferComponentType)
151 {
152 case GL_UNSIGNED_NORMALIZED:
153 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
154 // ReadPixels with BGRA even if the extension is not present
155 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
156 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
157 type == GL_UNSIGNED_BYTE);
158
159 case GL_SIGNED_NORMALIZED:
160 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
161
162 case GL_INT:
163 return (format == GL_RGBA_INTEGER && type == GL_INT);
164
165 case GL_UNSIGNED_INT:
166 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
167
168 case GL_FLOAT:
169 return (format == GL_RGBA && type == GL_FLOAT);
170
171 default:
172 UNREACHABLE();
173 return false;
174 }
175}
176
Geoff Langf41a7152016-09-19 15:11:17 -0400177bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500178{
179 switch (cap)
180 {
Geoff Langf41a7152016-09-19 15:11:17 -0400181 // EXT_multisample_compatibility
182 case GL_MULTISAMPLE_EXT:
183 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
184 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300185
Geoff Langf41a7152016-09-19 15:11:17 -0400186 case GL_CULL_FACE:
187 case GL_POLYGON_OFFSET_FILL:
188 case GL_SAMPLE_ALPHA_TO_COVERAGE:
189 case GL_SAMPLE_COVERAGE:
190 case GL_SCISSOR_TEST:
191 case GL_STENCIL_TEST:
192 case GL_DEPTH_TEST:
193 case GL_BLEND:
194 case GL_DITHER:
195 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500196
Geoff Langf41a7152016-09-19 15:11:17 -0400197 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
198 case GL_RASTERIZER_DISCARD:
199 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500200
Geoff Langf41a7152016-09-19 15:11:17 -0400201 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
202 case GL_DEBUG_OUTPUT:
203 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500204
Geoff Langf41a7152016-09-19 15:11:17 -0400205 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
206 return queryOnly && context->getExtensions().bindGeneratesResource;
207
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700208 case GL_FRAMEBUFFER_SRGB_EXT:
209 return context->getExtensions().sRGBWriteControl;
210
Geoff Lang3b573612016-10-31 14:08:10 -0400211 case GL_SAMPLE_MASK:
Geoff Lang3b573612016-10-31 14:08:10 -0400212 return context->getClientVersion() >= Version(3, 1);
213
Geoff Langf41a7152016-09-19 15:11:17 -0400214 default:
215 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500216 }
217}
218
Geoff Lang62fce5b2016-09-30 10:46:35 -0400219bool ValidateReadPixelsBase(ValidationContext *context,
220 GLint x,
221 GLint y,
222 GLsizei width,
223 GLsizei height,
224 GLenum format,
225 GLenum type,
226 GLsizei bufSize,
227 GLsizei *length,
228 GLvoid *pixels)
229{
230 if (length != nullptr)
231 {
232 *length = 0;
233 }
234
235 if (width < 0 || height < 0)
236 {
237 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
238 return false;
239 }
240
241 auto readFramebuffer = context->getGLState().getReadFramebuffer();
242
243 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
244 {
245 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
246 return false;
247 }
248
249 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
250 {
251 context->handleError(Error(GL_INVALID_OPERATION));
252 return false;
253 }
254
255 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
256 ASSERT(framebuffer);
257
258 if (framebuffer->getReadBufferState() == GL_NONE)
259 {
260 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
261 return false;
262 }
263
264 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500265 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
266 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
267 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
268 // situation is an application error that would lead to a crash in ANGLE.
269 if (readBuffer == nullptr)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400270 {
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500271 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
Geoff Lang62fce5b2016-09-30 10:46:35 -0400272 return false;
273 }
274
275 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
276 GLenum currentType = framebuffer->getImplementationColorReadType();
277 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
278
279 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
280 bool validFormatTypeCombination =
281 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
282
283 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
284 {
285 context->handleError(Error(GL_INVALID_OPERATION));
286 return false;
287 }
288
289 // Check for pixel pack buffer related API errors
290 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
291 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
292 {
293 // ...the buffer object's data store is currently mapped.
294 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
295 return false;
296 }
297
298 // .. the data would be packed to the buffer object such that the memory writes required
299 // would exceed the data store size.
300 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
301 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
302 const gl::Extents size(width, height, 1);
303 const auto &pack = context->getGLState().getPackState();
304
305 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
306 if (endByteOrErr.isError())
307 {
308 context->handleError(endByteOrErr.getError());
309 return false;
310 }
311
312 size_t endByte = endByteOrErr.getResult();
313 if (bufSize >= 0)
314 {
315
316 if (static_cast<size_t>(bufSize) < endByte)
317 {
318 context->handleError(
319 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
320 return false;
321 }
322 }
323
324 if (pixelPackBuffer != nullptr)
325 {
326 CheckedNumeric<size_t> checkedEndByte(endByte);
327 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
328 checkedEndByte += checkedOffset;
329
330 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
331 {
332 // Overflow past the end of the buffer
333 context->handleError(
334 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
335 return false;
336 }
337 }
338
339 if (length != nullptr)
340 {
341 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
342 {
343 context->handleError(
344 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
345 return false;
346 }
347
348 *length = static_cast<GLsizei>(endByte);
349 }
350
351 return true;
352}
353
Geoff Lang740d9022016-10-07 11:20:52 -0400354bool ValidateGetRenderbufferParameterivBase(Context *context,
355 GLenum target,
356 GLenum pname,
357 GLsizei *length)
358{
359 if (length)
360 {
361 *length = 0;
362 }
363
364 if (target != GL_RENDERBUFFER)
365 {
366 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
367 return false;
368 }
369
370 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
371 if (renderbuffer == nullptr)
372 {
373 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
374 return false;
375 }
376
377 switch (pname)
378 {
379 case GL_RENDERBUFFER_WIDTH:
380 case GL_RENDERBUFFER_HEIGHT:
381 case GL_RENDERBUFFER_INTERNAL_FORMAT:
382 case GL_RENDERBUFFER_RED_SIZE:
383 case GL_RENDERBUFFER_GREEN_SIZE:
384 case GL_RENDERBUFFER_BLUE_SIZE:
385 case GL_RENDERBUFFER_ALPHA_SIZE:
386 case GL_RENDERBUFFER_DEPTH_SIZE:
387 case GL_RENDERBUFFER_STENCIL_SIZE:
388 break;
389
390 case GL_RENDERBUFFER_SAMPLES_ANGLE:
391 if (!context->getExtensions().framebufferMultisample)
392 {
393 context->handleError(
394 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
395 return false;
396 }
397 break;
398
399 default:
400 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
401 return false;
402 }
403
404 if (length)
405 {
406 *length = 1;
407 }
408 return true;
409}
410
Geoff Langd7d0ed32016-10-07 11:33:51 -0400411bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
412{
413 if (length)
414 {
415 *length = 0;
416 }
417
418 if (GetValidShader(context, shader) == nullptr)
419 {
420 return false;
421 }
422
423 switch (pname)
424 {
425 case GL_SHADER_TYPE:
426 case GL_DELETE_STATUS:
427 case GL_COMPILE_STATUS:
428 case GL_INFO_LOG_LENGTH:
429 case GL_SHADER_SOURCE_LENGTH:
430 break;
431
432 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
433 if (!context->getExtensions().translatedShaderSource)
434 {
435 context->handleError(
436 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
437 return false;
438 }
439 break;
440
441 default:
442 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
443 return false;
444 }
445
446 if (length)
447 {
448 *length = 1;
449 }
450 return true;
451}
452
Geoff Langc1984ed2016-10-07 12:41:00 -0400453bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
454{
455 if (length)
456 {
457 *length = 0;
458 }
459
460 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
461 {
462 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
463 return false;
464 }
465
466 if (context->getTargetTexture(target) == nullptr)
467 {
468 // Should only be possible for external textures
469 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
470 return false;
471 }
472
473 switch (pname)
474 {
475 case GL_TEXTURE_MAG_FILTER:
476 case GL_TEXTURE_MIN_FILTER:
477 case GL_TEXTURE_WRAP_S:
478 case GL_TEXTURE_WRAP_T:
479 break;
480
481 case GL_TEXTURE_USAGE_ANGLE:
482 if (!context->getExtensions().textureUsage)
483 {
484 context->handleError(
485 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
486 return false;
487 }
488 break;
489
490 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
491 if (!context->getExtensions().textureFilterAnisotropic)
492 {
493 context->handleError(
494 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
495 return false;
496 }
497 break;
498
499 case GL_TEXTURE_IMMUTABLE_FORMAT:
500 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
501 {
502 context->handleError(
503 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
504 return false;
505 }
506 break;
507
508 case GL_TEXTURE_WRAP_R:
509 case GL_TEXTURE_IMMUTABLE_LEVELS:
510 case GL_TEXTURE_SWIZZLE_R:
511 case GL_TEXTURE_SWIZZLE_G:
512 case GL_TEXTURE_SWIZZLE_B:
513 case GL_TEXTURE_SWIZZLE_A:
514 case GL_TEXTURE_BASE_LEVEL:
515 case GL_TEXTURE_MAX_LEVEL:
516 case GL_TEXTURE_MIN_LOD:
517 case GL_TEXTURE_MAX_LOD:
518 case GL_TEXTURE_COMPARE_MODE:
519 case GL_TEXTURE_COMPARE_FUNC:
520 if (context->getClientMajorVersion() < 3)
521 {
522 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
523 return false;
524 }
525 break;
526
Geoff Lang81c6b572016-10-19 14:07:52 -0700527 case GL_TEXTURE_SRGB_DECODE_EXT:
528 if (!context->getExtensions().textureSRGBDecode)
529 {
530 context->handleError(
531 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
532 return false;
533 }
534 break;
535
Geoff Langc1984ed2016-10-07 12:41:00 -0400536 default:
537 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
538 return false;
539 }
540
541 if (length)
542 {
543 *length = 1;
544 }
545 return true;
546}
547
548template <typename ParamType>
549bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
550{
551 switch (ConvertToGLenum(params[0]))
552 {
553 case GL_CLAMP_TO_EDGE:
554 break;
555
556 case GL_REPEAT:
557 case GL_MIRRORED_REPEAT:
558 if (isExternalTextureTarget)
559 {
560 // OES_EGL_image_external specifies this error.
561 context->handleError(Error(
562 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
563 return false;
564 }
565 break;
566
567 default:
568 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
569 return false;
570 }
571
572 return true;
573}
574
575template <typename ParamType>
576bool ValidateTextureMinFilterValue(Context *context,
577 ParamType *params,
578 bool isExternalTextureTarget)
579{
580 switch (ConvertToGLenum(params[0]))
581 {
582 case GL_NEAREST:
583 case GL_LINEAR:
584 break;
585
586 case GL_NEAREST_MIPMAP_NEAREST:
587 case GL_LINEAR_MIPMAP_NEAREST:
588 case GL_NEAREST_MIPMAP_LINEAR:
589 case GL_LINEAR_MIPMAP_LINEAR:
590 if (isExternalTextureTarget)
591 {
592 // OES_EGL_image_external specifies this error.
593 context->handleError(
594 Error(GL_INVALID_ENUM,
595 "external textures only support NEAREST and LINEAR filtering"));
596 return false;
597 }
598 break;
599
600 default:
601 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
602 return false;
603 }
604
605 return true;
606}
607
608template <typename ParamType>
609bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
610{
611 switch (ConvertToGLenum(params[0]))
612 {
613 case GL_NEAREST:
614 case GL_LINEAR:
615 break;
616
617 default:
618 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
619 return false;
620 }
621
622 return true;
623}
624
625template <typename ParamType>
626bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
627{
628 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
629 switch (ConvertToGLenum(params[0]))
630 {
631 case GL_NONE:
632 case GL_COMPARE_REF_TO_TEXTURE:
633 break;
634
635 default:
636 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
637 return false;
638 }
639
640 return true;
641}
642
643template <typename ParamType>
644bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
645{
646 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
647 switch (ConvertToGLenum(params[0]))
648 {
649 case GL_LEQUAL:
650 case GL_GEQUAL:
651 case GL_LESS:
652 case GL_GREATER:
653 case GL_EQUAL:
654 case GL_NOTEQUAL:
655 case GL_ALWAYS:
656 case GL_NEVER:
657 break;
658
659 default:
660 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
661 return false;
662 }
663
664 return true;
665}
666
667template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700668bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
669{
670 if (!context->getExtensions().textureSRGBDecode)
671 {
672 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
673 return false;
674 }
675
676 switch (ConvertToGLenum(params[0]))
677 {
678 case GL_DECODE_EXT:
679 case GL_SKIP_DECODE_EXT:
680 break;
681
682 default:
683 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
684 return false;
685 }
686
687 return true;
688}
689
690template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400691bool ValidateTexParameterBase(Context *context,
692 GLenum target,
693 GLenum pname,
694 GLsizei bufSize,
695 ParamType *params)
696{
697 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
698 {
699 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
700 return false;
701 }
702
703 if (context->getTargetTexture(target) == nullptr)
704 {
705 // Should only be possible for external textures
706 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
707 return false;
708 }
709
710 const GLsizei minBufSize = 1;
711 if (bufSize >= 0 && bufSize < minBufSize)
712 {
713 context->handleError(
714 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
715 return false;
716 }
717
718 switch (pname)
719 {
720 case GL_TEXTURE_WRAP_R:
721 case GL_TEXTURE_SWIZZLE_R:
722 case GL_TEXTURE_SWIZZLE_G:
723 case GL_TEXTURE_SWIZZLE_B:
724 case GL_TEXTURE_SWIZZLE_A:
725 case GL_TEXTURE_BASE_LEVEL:
726 case GL_TEXTURE_MAX_LEVEL:
727 case GL_TEXTURE_COMPARE_MODE:
728 case GL_TEXTURE_COMPARE_FUNC:
729 case GL_TEXTURE_MIN_LOD:
730 case GL_TEXTURE_MAX_LOD:
731 if (context->getClientMajorVersion() < 3)
732 {
733 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
734 return false;
735 }
736 if (target == GL_TEXTURE_EXTERNAL_OES &&
737 !context->getExtensions().eglImageExternalEssl3)
738 {
739 context->handleError(Error(GL_INVALID_ENUM,
740 "ES3 texture parameters are not available without "
741 "GL_OES_EGL_image_external_essl3."));
742 return false;
743 }
744 break;
745
746 default:
747 break;
748 }
749
750 switch (pname)
751 {
752 case GL_TEXTURE_WRAP_S:
753 case GL_TEXTURE_WRAP_T:
754 case GL_TEXTURE_WRAP_R:
755 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
756 {
757 return false;
758 }
759 break;
760
761 case GL_TEXTURE_MIN_FILTER:
762 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
763 {
764 return false;
765 }
766 break;
767
768 case GL_TEXTURE_MAG_FILTER:
769 if (!ValidateTextureMagFilterValue(context, params))
770 {
771 return false;
772 }
773 break;
774
775 case GL_TEXTURE_USAGE_ANGLE:
776 switch (ConvertToGLenum(params[0]))
777 {
778 case GL_NONE:
779 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
780 break;
781
782 default:
783 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
784 return false;
785 }
786 break;
787
788 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
789 if (!context->getExtensions().textureFilterAnisotropic)
790 {
791 context->handleError(
792 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
793 return false;
794 }
795
796 // we assume the parameter passed to this validation method is truncated, not rounded
797 if (params[0] < 1)
798 {
799 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
800 return false;
801 }
802 break;
803
804 case GL_TEXTURE_MIN_LOD:
805 case GL_TEXTURE_MAX_LOD:
806 // any value is permissible
807 break;
808
809 case GL_TEXTURE_COMPARE_MODE:
810 if (!ValidateTextureCompareModeValue(context, params))
811 {
812 return false;
813 }
814 break;
815
816 case GL_TEXTURE_COMPARE_FUNC:
817 if (!ValidateTextureCompareFuncValue(context, params))
818 {
819 return false;
820 }
821 break;
822
823 case GL_TEXTURE_SWIZZLE_R:
824 case GL_TEXTURE_SWIZZLE_G:
825 case GL_TEXTURE_SWIZZLE_B:
826 case GL_TEXTURE_SWIZZLE_A:
827 switch (ConvertToGLenum(params[0]))
828 {
829 case GL_RED:
830 case GL_GREEN:
831 case GL_BLUE:
832 case GL_ALPHA:
833 case GL_ZERO:
834 case GL_ONE:
835 break;
836
837 default:
838 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
839 return false;
840 }
841 break;
842
843 case GL_TEXTURE_BASE_LEVEL:
844 if (params[0] < 0)
845 {
846 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
847 return false;
848 }
849 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
850 {
851 context->handleError(
852 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
853 return false;
854 }
855 break;
856
857 case GL_TEXTURE_MAX_LEVEL:
858 if (params[0] < 0)
859 {
860 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
861 return false;
862 }
863 break;
864
Geoff Lang3b573612016-10-31 14:08:10 -0400865 case GL_DEPTH_STENCIL_TEXTURE_MODE:
866 if (context->getClientVersion() < Version(3, 1))
867 {
868 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
869 return false;
870 }
Geoff Lang9f090372016-12-02 10:20:43 -0500871 switch (ConvertToGLenum(params[0]))
872 {
873 case GL_DEPTH_COMPONENT:
874 case GL_STENCIL_INDEX:
875 break;
876
877 default:
878 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
879 return false;
880 }
Geoff Lang3b573612016-10-31 14:08:10 -0400881 break;
882
Geoff Lang81c6b572016-10-19 14:07:52 -0700883 case GL_TEXTURE_SRGB_DECODE_EXT:
884 if (!ValidateTextureSRGBDecodeValue(context, params))
885 {
886 return false;
887 }
888 break;
889
Geoff Langc1984ed2016-10-07 12:41:00 -0400890 default:
891 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
892 return false;
893 }
894
895 return true;
896}
897
898template <typename ParamType>
899bool ValidateSamplerParameterBase(Context *context,
900 GLuint sampler,
901 GLenum pname,
902 GLsizei bufSize,
903 ParamType *params)
904{
905 if (context->getClientMajorVersion() < 3)
906 {
907 context->handleError(
908 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
909 return false;
910 }
911
912 if (!context->isSampler(sampler))
913 {
914 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
915 return false;
916 }
917
918 const GLsizei minBufSize = 1;
919 if (bufSize >= 0 && bufSize < minBufSize)
920 {
921 context->handleError(
922 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
923 return false;
924 }
925
926 switch (pname)
927 {
928 case GL_TEXTURE_WRAP_S:
929 case GL_TEXTURE_WRAP_T:
930 case GL_TEXTURE_WRAP_R:
931 if (!ValidateTextureWrapModeValue(context, params, false))
932 {
933 return false;
934 }
935 break;
936
937 case GL_TEXTURE_MIN_FILTER:
938 if (!ValidateTextureMinFilterValue(context, params, false))
939 {
940 return false;
941 }
942 break;
943
944 case GL_TEXTURE_MAG_FILTER:
945 if (!ValidateTextureMagFilterValue(context, params))
946 {
947 return false;
948 }
949 break;
950
951 case GL_TEXTURE_MIN_LOD:
952 case GL_TEXTURE_MAX_LOD:
953 // any value is permissible
954 break;
955
956 case GL_TEXTURE_COMPARE_MODE:
957 if (!ValidateTextureCompareModeValue(context, params))
958 {
959 return false;
960 }
961 break;
962
963 case GL_TEXTURE_COMPARE_FUNC:
964 if (!ValidateTextureCompareFuncValue(context, params))
965 {
966 return false;
967 }
968 break;
969
Geoff Lang81c6b572016-10-19 14:07:52 -0700970 case GL_TEXTURE_SRGB_DECODE_EXT:
971 if (!ValidateTextureSRGBDecodeValue(context, params))
972 {
973 return false;
974 }
975 break;
976
Geoff Langc1984ed2016-10-07 12:41:00 -0400977 default:
978 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
979 return false;
980 }
981
982 return true;
983}
984
985bool ValidateGetSamplerParameterBase(Context *context,
986 GLuint sampler,
987 GLenum pname,
988 GLsizei *length)
989{
990 if (length)
991 {
992 *length = 0;
993 }
994
995 if (context->getClientMajorVersion() < 3)
996 {
997 context->handleError(
998 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
999 return false;
1000 }
1001
1002 if (!context->isSampler(sampler))
1003 {
1004 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
1005 return false;
1006 }
1007
1008 switch (pname)
1009 {
1010 case GL_TEXTURE_WRAP_S:
1011 case GL_TEXTURE_WRAP_T:
1012 case GL_TEXTURE_WRAP_R:
1013 case GL_TEXTURE_MIN_FILTER:
1014 case GL_TEXTURE_MAG_FILTER:
1015 case GL_TEXTURE_MIN_LOD:
1016 case GL_TEXTURE_MAX_LOD:
1017 case GL_TEXTURE_COMPARE_MODE:
1018 case GL_TEXTURE_COMPARE_FUNC:
1019 break;
1020
Geoff Lang81c6b572016-10-19 14:07:52 -07001021 case GL_TEXTURE_SRGB_DECODE_EXT:
1022 if (!context->getExtensions().textureSRGBDecode)
1023 {
1024 context->handleError(
1025 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
1026 return false;
1027 }
1028 break;
1029
Geoff Langc1984ed2016-10-07 12:41:00 -04001030 default:
1031 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1032 return false;
1033 }
1034
1035 if (length)
1036 {
1037 *length = 1;
1038 }
1039 return true;
1040}
1041
Geoff Lang0b031062016-10-13 14:30:04 -04001042bool ValidateGetVertexAttribBase(Context *context,
1043 GLuint index,
1044 GLenum pname,
1045 GLsizei *length,
1046 bool pointer,
1047 bool pureIntegerEntryPoint)
1048{
1049 if (length)
1050 {
1051 *length = 0;
1052 }
1053
1054 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1055 {
1056 context->handleError(
1057 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1058 return false;
1059 }
1060
1061 if (index >= context->getCaps().maxVertexAttributes)
1062 {
1063 context->handleError(Error(
1064 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1065 return false;
1066 }
1067
1068 if (pointer)
1069 {
1070 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1071 {
1072 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1073 return false;
1074 }
1075 }
1076 else
1077 {
1078 switch (pname)
1079 {
1080 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1081 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1082 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1083 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1084 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1085 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1086 case GL_CURRENT_VERTEX_ATTRIB:
1087 break;
1088
1089 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1090 static_assert(
1091 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1092 "ANGLE extension enums not equal to GL enums.");
1093 if (context->getClientMajorVersion() < 3 &&
1094 !context->getExtensions().instancedArrays)
1095 {
1096 context->handleError(Error(GL_INVALID_ENUM,
1097 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1098 "3.0 or GL_ANGLE_instanced_arrays."));
1099 return false;
1100 }
1101 break;
1102
1103 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1104 if (context->getClientMajorVersion() < 3)
1105 {
1106 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1107 return false;
1108 }
1109 break;
1110
1111 default:
1112 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1113 return false;
1114 }
1115 }
1116
1117 if (length)
1118 {
1119 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1120 {
1121 *length = 4;
1122 }
1123 else
1124 {
1125 *length = 1;
1126 }
1127 }
1128
1129 return true;
1130}
1131
Geoff Lang6899b872016-10-14 11:30:13 -04001132bool ValidateGetActiveUniformBlockivBase(Context *context,
1133 GLuint program,
1134 GLuint uniformBlockIndex,
1135 GLenum pname,
1136 GLsizei *length)
1137{
1138 if (length)
1139 {
1140 *length = 0;
1141 }
1142
1143 if (context->getClientMajorVersion() < 3)
1144 {
1145 context->handleError(
1146 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1147 return false;
1148 }
1149
1150 Program *programObject = GetValidProgram(context, program);
1151 if (!programObject)
1152 {
1153 return false;
1154 }
1155
1156 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1157 {
1158 context->handleError(
1159 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1160 return false;
1161 }
1162
1163 switch (pname)
1164 {
1165 case GL_UNIFORM_BLOCK_BINDING:
1166 case GL_UNIFORM_BLOCK_DATA_SIZE:
1167 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1168 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1169 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1170 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1171 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1172 break;
1173
1174 default:
1175 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1176 return false;
1177 }
1178
1179 if (length)
1180 {
1181 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1182 {
1183 const UniformBlock &uniformBlock =
1184 programObject->getUniformBlockByIndex(uniformBlockIndex);
1185 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1186 }
1187 else
1188 {
1189 *length = 1;
1190 }
1191 }
1192
1193 return true;
1194}
1195
Geoff Langebebe1c2016-10-14 12:01:31 -04001196bool ValidateGetBufferParameterBase(ValidationContext *context,
1197 GLenum target,
1198 GLenum pname,
1199 bool pointerVersion,
1200 GLsizei *numParams)
1201{
1202 if (numParams)
1203 {
1204 *numParams = 0;
1205 }
1206
1207 if (!ValidBufferTarget(context, target))
1208 {
1209 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1210 return false;
1211 }
1212
1213 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1214 if (!buffer)
1215 {
1216 // A null buffer means that "0" is bound to the requested buffer target
1217 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1218 return false;
1219 }
1220
1221 const Extensions &extensions = context->getExtensions();
1222
1223 switch (pname)
1224 {
1225 case GL_BUFFER_USAGE:
1226 case GL_BUFFER_SIZE:
1227 break;
1228
1229 case GL_BUFFER_ACCESS_OES:
1230 if (!extensions.mapBuffer)
1231 {
1232 context->handleError(
1233 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
1234 return false;
1235 }
1236 break;
1237
1238 case GL_BUFFER_MAPPED:
1239 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1240 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1241 !extensions.mapBufferRange)
1242 {
1243 context->handleError(Error(
1244 GL_INVALID_ENUM,
1245 "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
1246 return false;
1247 }
1248 break;
1249
1250 case GL_BUFFER_MAP_POINTER:
1251 if (!pointerVersion)
1252 {
1253 context->handleError(
1254 Error(GL_INVALID_ENUM,
1255 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1256 return false;
1257 }
1258 break;
1259
1260 case GL_BUFFER_ACCESS_FLAGS:
1261 case GL_BUFFER_MAP_OFFSET:
1262 case GL_BUFFER_MAP_LENGTH:
1263 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1264 {
1265 context->handleError(Error(
1266 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1267 return false;
1268 }
1269 break;
1270
1271 default:
1272 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1273 return false;
1274 }
1275
1276 // All buffer parameter queries return one value.
1277 if (numParams)
1278 {
1279 *numParams = 1;
1280 }
1281
1282 return true;
1283}
1284
Geoff Lang0a9661f2016-10-20 10:59:20 -07001285bool ValidateGetInternalFormativBase(Context *context,
1286 GLenum target,
1287 GLenum internalformat,
1288 GLenum pname,
1289 GLsizei bufSize,
1290 GLsizei *numParams)
1291{
1292 if (numParams)
1293 {
1294 *numParams = 0;
1295 }
1296
1297 if (context->getClientMajorVersion() < 3)
1298 {
1299 context->handleError(
1300 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1301 return false;
1302 }
1303
1304 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1305 if (!formatCaps.renderable)
1306 {
1307 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1308 return false;
1309 }
1310
1311 switch (target)
1312 {
1313 case GL_RENDERBUFFER:
1314 break;
1315
1316 default:
1317 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1318 return false;
1319 }
1320
1321 if (bufSize < 0)
1322 {
1323 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1324 return false;
1325 }
1326
1327 GLsizei maxWriteParams = 0;
1328 switch (pname)
1329 {
1330 case GL_NUM_SAMPLE_COUNTS:
1331 maxWriteParams = 1;
1332 break;
1333
1334 case GL_SAMPLES:
1335 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1336 break;
1337
1338 default:
1339 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1340 return false;
1341 }
1342
1343 if (numParams)
1344 {
1345 // glGetInternalFormativ will not overflow bufSize
1346 *numParams = std::min(bufSize, maxWriteParams);
1347 }
1348
1349 return true;
1350}
1351
Geoff Langf41a7152016-09-19 15:11:17 -04001352} // anonymous namespace
1353
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001354bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001355{
Jamie Madilld7460c72014-01-21 16:38:14 -05001356 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001357 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001358 case GL_TEXTURE_2D:
1359 case GL_TEXTURE_CUBE_MAP:
1360 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001361
He Yunchaoced53ae2016-11-29 15:00:51 +08001362 case GL_TEXTURE_3D:
1363 case GL_TEXTURE_2D_ARRAY:
1364 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001365
He Yunchaoced53ae2016-11-29 15:00:51 +08001366 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001367 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001368
He Yunchaoced53ae2016-11-29 15:00:51 +08001369 default:
1370 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001371 }
Jamie Madill35d15012013-10-07 10:46:37 -04001372}
1373
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001374bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1375{
1376 switch (target)
1377 {
1378 case GL_TEXTURE_2D:
1379 case GL_TEXTURE_CUBE_MAP:
1380 return true;
1381
1382 default:
1383 return false;
1384 }
1385}
1386
1387bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1388{
1389 switch (target)
1390 {
1391 case GL_TEXTURE_3D:
1392 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001393 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001394
1395 default:
1396 return false;
1397 }
1398}
1399
Ian Ewellbda75592016-04-18 17:25:54 -04001400// Most texture GL calls are not compatible with external textures, so we have a separate validation
1401// function for use in the GL calls that do
1402bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1403{
1404 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1405 (context->getExtensions().eglImageExternal ||
1406 context->getExtensions().eglStreamConsumerExternal);
1407}
1408
Shannon Woods4dfed832014-03-17 20:03:39 -04001409// This function differs from ValidTextureTarget in that the target must be
1410// usable as the destination of a 2D operation-- so a cube face is valid, but
1411// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001412// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001413bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001414{
1415 switch (target)
1416 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001417 case GL_TEXTURE_2D:
1418 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1419 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1420 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1421 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1422 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1423 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1424 return true;
1425 default:
1426 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001427 }
1428}
1429
1430bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1431{
1432 switch (target)
1433 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001434 case GL_TEXTURE_3D:
1435 case GL_TEXTURE_2D_ARRAY:
1436 return true;
1437 default:
1438 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001439 }
1440}
1441
He Yunchao11b038b2016-11-22 21:24:04 +08001442bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1443{
1444 switch (target)
1445 {
1446 case GL_TEXTURE_2D:
1447 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1448 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1449 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1450 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1451 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1452 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1453 case GL_TEXTURE_3D:
1454 case GL_TEXTURE_2D_ARRAY:
1455 case GL_TEXTURE_2D_MULTISAMPLE:
1456 return true;
1457 default:
1458 return false;
1459 }
1460}
1461
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001462bool ValidFramebufferTarget(GLenum target)
1463{
He Yunchaoced53ae2016-11-29 15:00:51 +08001464 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1465 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001466 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001467
1468 switch (target)
1469 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001470 case GL_FRAMEBUFFER:
1471 return true;
1472 case GL_READ_FRAMEBUFFER:
1473 return true;
1474 case GL_DRAW_FRAMEBUFFER:
1475 return true;
1476 default:
1477 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001478 }
1479}
1480
Jamie Madill29639852016-09-02 15:00:09 -04001481bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001482{
1483 switch (target)
1484 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001485 case GL_ARRAY_BUFFER:
1486 case GL_ELEMENT_ARRAY_BUFFER:
1487 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001488
He Yunchaoced53ae2016-11-29 15:00:51 +08001489 case GL_PIXEL_PACK_BUFFER:
1490 case GL_PIXEL_UNPACK_BUFFER:
1491 return (context->getExtensions().pixelBufferObject ||
1492 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001493
He Yunchaoced53ae2016-11-29 15:00:51 +08001494 case GL_COPY_READ_BUFFER:
1495 case GL_COPY_WRITE_BUFFER:
1496 case GL_TRANSFORM_FEEDBACK_BUFFER:
1497 case GL_UNIFORM_BUFFER:
1498 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001499
He Yunchaoced53ae2016-11-29 15:00:51 +08001500 case GL_ATOMIC_COUNTER_BUFFER:
1501 case GL_SHADER_STORAGE_BUFFER:
1502 case GL_DRAW_INDIRECT_BUFFER:
1503 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001504 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001505
He Yunchaoced53ae2016-11-29 15:00:51 +08001506 default:
1507 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001508 }
1509}
1510
Jamie Madillc29968b2016-01-20 11:17:23 -05001511bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001512{
Jamie Madillc29968b2016-01-20 11:17:23 -05001513 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001514 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001515 switch (target)
1516 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001517 case GL_TEXTURE_2D:
1518 maxDimension = caps.max2DTextureSize;
1519 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001520 case GL_TEXTURE_CUBE_MAP:
1521 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1522 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1523 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1524 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1525 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1526 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1527 maxDimension = caps.maxCubeMapTextureSize;
1528 break;
1529 case GL_TEXTURE_3D:
1530 maxDimension = caps.max3DTextureSize;
1531 break;
1532 case GL_TEXTURE_2D_ARRAY:
1533 maxDimension = caps.max2DTextureSize;
1534 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001535 case GL_TEXTURE_2D_MULTISAMPLE:
1536 maxDimension = caps.max2DTextureSize;
1537 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001538 default:
1539 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001540 }
1541
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001542 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001543}
1544
Geoff Langcc507aa2016-12-12 10:09:52 -05001545bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001546 GLenum target,
1547 GLint level,
1548 GLsizei width,
1549 GLsizei height,
1550 GLsizei depth,
1551 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001552{
1553 if (level < 0 || width < 0 || height < 0 || depth < 0)
1554 {
1555 return false;
1556 }
1557
Austin Kinross08528e12015-10-07 16:24:40 -07001558 // TexSubImage parameters can be NPOT without textureNPOT extension,
1559 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001560 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001561 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001562 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001563 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001564 {
1565 return false;
1566 }
1567
1568 if (!ValidMipLevel(context, target, level))
1569 {
1570 return false;
1571 }
1572
1573 return true;
1574}
1575
Geoff Lang0d8b7242015-09-09 14:56:53 -04001576bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1577{
1578 // List of compressed format that require that the texture size is smaller than or a multiple of
1579 // the compressed block size.
1580 switch (internalFormat)
1581 {
1582 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1583 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1584 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1585 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001586 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001587 return true;
1588
1589 default:
1590 return false;
1591 }
1592}
1593
Jamie Madillc29968b2016-01-20 11:17:23 -05001594bool ValidCompressedImageSize(const ValidationContext *context,
1595 GLenum internalFormat,
1596 GLsizei width,
1597 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001598{
Geoff Lang5d601382014-07-22 15:14:06 -04001599 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1600 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001601 {
1602 return false;
1603 }
1604
Geoff Lang0d8b7242015-09-09 14:56:53 -04001605 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001606 {
1607 return false;
1608 }
1609
Geoff Lang0d8b7242015-09-09 14:56:53 -04001610 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1611 {
1612 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1613 width % formatInfo.compressedBlockWidth != 0) ||
1614 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1615 height % formatInfo.compressedBlockHeight != 0))
1616 {
1617 return false;
1618 }
1619 }
1620
Geoff Langd4f180b2013-09-24 13:57:44 -04001621 return true;
1622}
1623
Geoff Langff5b2d52016-09-07 11:32:23 -04001624bool ValidImageDataSize(ValidationContext *context,
1625 GLenum textureTarget,
1626 GLsizei width,
1627 GLsizei height,
1628 GLsizei depth,
1629 GLenum internalFormat,
1630 GLenum type,
1631 const GLvoid *pixels,
1632 GLsizei imageSize)
1633{
1634 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1635 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1636 {
1637 // Checks are not required
1638 return true;
1639 }
1640
1641 // ...the data would be unpacked from the buffer object such that the memory reads required
1642 // would exceed the data store size.
1643 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1644 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1645 const gl::Extents size(width, height, depth);
1646 const auto &unpack = context->getGLState().getUnpackState();
1647
1648 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1649 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1650 if (endByteOrErr.isError())
1651 {
1652 context->handleError(endByteOrErr.getError());
1653 return false;
1654 }
1655
1656 GLuint endByte = endByteOrErr.getResult();
1657
1658 if (pixelUnpackBuffer)
1659 {
1660 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1661 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1662 checkedEndByte += checkedOffset;
1663
1664 if (!checkedEndByte.IsValid() ||
1665 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1666 {
1667 // Overflow past the end of the buffer
1668 context->handleError(Error(GL_INVALID_OPERATION));
1669 return false;
1670 }
1671 }
1672 else
1673 {
1674 ASSERT(imageSize >= 0);
1675 if (pixels == nullptr && imageSize != 0)
1676 {
1677 context->handleError(
1678 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001679 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001680 }
1681
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001682 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001683 {
1684 context->handleError(
1685 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1686 return false;
1687 }
1688 }
1689
1690 return true;
1691}
1692
Geoff Lang37dde692014-01-31 16:34:54 -05001693bool ValidQueryType(const Context *context, GLenum queryType)
1694{
He Yunchaoced53ae2016-11-29 15:00:51 +08001695 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1696 "GL extension enums not equal.");
1697 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1698 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001699
1700 switch (queryType)
1701 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001702 case GL_ANY_SAMPLES_PASSED:
1703 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1704 return true;
1705 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1706 return (context->getClientMajorVersion() >= 3);
1707 case GL_TIME_ELAPSED_EXT:
1708 return context->getExtensions().disjointTimerQuery;
1709 case GL_COMMANDS_COMPLETED_CHROMIUM:
1710 return context->getExtensions().syncQuery;
1711 default:
1712 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001713 }
1714}
1715
Jamie Madillef300b12016-10-07 15:12:09 -04001716Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001717{
He Yunchaoced53ae2016-11-29 15:00:51 +08001718 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1719 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1720 // or program object and INVALID_OPERATION if the provided name identifies an object
1721 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001722
Dian Xiang769769a2015-09-09 15:20:08 -07001723 Program *validProgram = context->getProgram(id);
1724
1725 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001726 {
Dian Xiang769769a2015-09-09 15:20:08 -07001727 if (context->getShader(id))
1728 {
Jamie Madill437fa652016-05-03 15:13:24 -04001729 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001730 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1731 }
1732 else
1733 {
Jamie Madill437fa652016-05-03 15:13:24 -04001734 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001735 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001736 }
Dian Xiang769769a2015-09-09 15:20:08 -07001737
1738 return validProgram;
1739}
1740
Jamie Madillef300b12016-10-07 15:12:09 -04001741Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001742{
1743 // See ValidProgram for spec details.
1744
1745 Shader *validShader = context->getShader(id);
1746
1747 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001748 {
Dian Xiang769769a2015-09-09 15:20:08 -07001749 if (context->getProgram(id))
1750 {
Jamie Madill437fa652016-05-03 15:13:24 -04001751 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001752 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1753 }
1754 else
1755 {
Jamie Madill437fa652016-05-03 15:13:24 -04001756 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001757 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001758 }
Dian Xiang769769a2015-09-09 15:20:08 -07001759
1760 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001761}
1762
Geoff Langb1196682014-07-23 13:47:29 -04001763bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001764{
1765 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1766 {
1767 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1768
Geoff Langaae65a42014-05-26 12:43:44 -04001769 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001770 {
Jamie Madill437fa652016-05-03 15:13:24 -04001771 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001772 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001773 }
1774 }
1775 else
1776 {
1777 switch (attachment)
1778 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001779 case GL_DEPTH_ATTACHMENT:
1780 case GL_STENCIL_ATTACHMENT:
1781 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001782
He Yunchaoced53ae2016-11-29 15:00:51 +08001783 case GL_DEPTH_STENCIL_ATTACHMENT:
1784 if (!context->getExtensions().webglCompatibility &&
1785 context->getClientMajorVersion() < 3)
1786 {
1787 context->handleError(Error(GL_INVALID_ENUM));
1788 return false;
1789 }
1790 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001791
He Yunchaoced53ae2016-11-29 15:00:51 +08001792 default:
1793 context->handleError(Error(GL_INVALID_ENUM));
1794 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001795 }
1796 }
1797
1798 return true;
1799}
1800
He Yunchaoced53ae2016-11-29 15:00:51 +08001801bool ValidateRenderbufferStorageParametersBase(gl::Context *context,
1802 GLenum target,
1803 GLsizei samples,
1804 GLenum internalformat,
1805 GLsizei width,
1806 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001807{
1808 switch (target)
1809 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001810 case GL_RENDERBUFFER:
1811 break;
1812 default:
1813 context->handleError(Error(GL_INVALID_ENUM));
1814 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001815 }
1816
1817 if (width < 0 || height < 0 || samples < 0)
1818 {
Jamie Madill437fa652016-05-03 15:13:24 -04001819 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001820 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001821 }
1822
Geoff Langd87878e2014-09-19 15:42:59 -04001823 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1824 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001825 {
Jamie Madill437fa652016-05-03 15:13:24 -04001826 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001827 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001828 }
1829
1830 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1831 // 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 -08001832 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001833 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001834 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001835 {
Jamie Madill437fa652016-05-03 15:13:24 -04001836 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001837 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001838 }
1839
Geoff Langaae65a42014-05-26 12:43:44 -04001840 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001841 {
Jamie Madill437fa652016-05-03 15:13:24 -04001842 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001843 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001844 }
1845
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001846 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001847 if (handle == 0)
1848 {
Jamie Madill437fa652016-05-03 15:13:24 -04001849 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001850 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001851 }
1852
1853 return true;
1854}
1855
He Yunchaoced53ae2016-11-29 15:00:51 +08001856bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context,
1857 GLenum target,
1858 GLsizei samples,
1859 GLenum internalformat,
1860 GLsizei width,
1861 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -08001862{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001863 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001864
1865 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001866 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001867 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001868 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001869 {
Jamie Madill437fa652016-05-03 15:13:24 -04001870 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001871 return false;
1872 }
1873
1874 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1875 // the specified storage. This is different than ES 3.0 in which a sample number higher
1876 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001877 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001878 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001879 {
Geoff Langa4903b72015-03-02 16:02:48 -08001880 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1881 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1882 {
Jamie Madill437fa652016-05-03 15:13:24 -04001883 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001884 return false;
1885 }
Corentin Walleze0902642014-11-04 12:32:15 -08001886 }
1887
He Yunchaoced53ae2016-11-29 15:00:51 +08001888 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
1889 width, height);
Corentin Walleze0902642014-11-04 12:32:15 -08001890}
1891
He Yunchaoced53ae2016-11-29 15:00:51 +08001892bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1893 GLenum target,
1894 GLenum attachment,
1895 GLenum renderbuffertarget,
1896 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001897{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001898 if (!ValidFramebufferTarget(target))
1899 {
Jamie Madill437fa652016-05-03 15:13:24 -04001900 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001901 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001902 }
1903
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001904 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001905
Jamie Madill84115c92015-04-23 15:00:07 -04001906 ASSERT(framebuffer);
1907 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001908 {
Jamie Madill437fa652016-05-03 15:13:24 -04001909 context->handleError(
1910 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001911 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001912 }
1913
Jamie Madillb4472272014-07-03 10:38:55 -04001914 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001915 {
Jamie Madillb4472272014-07-03 10:38:55 -04001916 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001917 }
1918
Jamie Madillab9d82c2014-01-21 16:38:14 -05001919 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1920 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1921 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1922 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1923 if (renderbuffer != 0)
1924 {
1925 if (!context->getRenderbuffer(renderbuffer))
1926 {
Jamie Madill437fa652016-05-03 15:13:24 -04001927 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001928 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001929 }
1930 }
1931
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001932 return true;
1933}
1934
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001935bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001936 GLint srcX0,
1937 GLint srcY0,
1938 GLint srcX1,
1939 GLint srcY1,
1940 GLint dstX0,
1941 GLint dstY0,
1942 GLint dstX1,
1943 GLint dstY1,
1944 GLbitfield mask,
1945 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001946{
1947 switch (filter)
1948 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001949 case GL_NEAREST:
1950 break;
1951 case GL_LINEAR:
1952 break;
1953 default:
1954 context->handleError(Error(GL_INVALID_ENUM));
1955 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001956 }
1957
1958 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1959 {
Jamie Madill437fa652016-05-03 15:13:24 -04001960 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001961 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001962 }
1963
1964 if (mask == 0)
1965 {
1966 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1967 // buffers are copied.
1968 return false;
1969 }
1970
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001971 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1972 // color buffer, leaving only nearest being unfiltered from above
1973 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1974 {
Jamie Madill437fa652016-05-03 15:13:24 -04001975 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001976 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001977 }
1978
Jamie Madill51f40ec2016-06-15 14:06:00 -04001979 const auto &glState = context->getGLState();
1980 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1981 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001982
1983 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001984 {
Jamie Madill437fa652016-05-03 15:13:24 -04001985 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001986 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001987 }
1988
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001989 if (readFramebuffer->id() == drawFramebuffer->id())
1990 {
1991 context->handleError(Error(GL_INVALID_OPERATION));
1992 return false;
1993 }
1994
Jamie Madill51f40ec2016-06-15 14:06:00 -04001995 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001996 {
Jamie Madill437fa652016-05-03 15:13:24 -04001997 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001998 return false;
1999 }
2000
Jamie Madill51f40ec2016-06-15 14:06:00 -04002001 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05002002 {
Jamie Madill437fa652016-05-03 15:13:24 -04002003 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05002004 return false;
2005 }
2006
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002007 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002008 {
Jamie Madill437fa652016-05-03 15:13:24 -04002009 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002010 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002011 }
2012
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002013 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
2014
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002015 if (mask & GL_COLOR_BUFFER_BIT)
2016 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002017 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05002018 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002019
He Yunchao66a41a22016-12-15 16:45:05 +08002020 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002021 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002022 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002023
Geoff Langa15472a2015-08-11 11:48:03 -04002024 for (size_t drawbufferIdx = 0;
2025 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002026 {
Geoff Langa15472a2015-08-11 11:48:03 -04002027 const FramebufferAttachment *attachment =
2028 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2029 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002030 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002031 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002032
Geoff Langb2f3d052013-08-13 12:49:27 -04002033 // The GL ES 3.0.2 spec (pg 193) states that:
2034 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002035 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2036 // as well
2037 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2038 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002039 // Changes with EXT_color_buffer_float:
2040 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002041 GLenum readComponentType = readFormat.info->componentType;
2042 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002043 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002044 readComponentType == GL_SIGNED_NORMALIZED);
2045 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2046 drawComponentType == GL_SIGNED_NORMALIZED);
2047
2048 if (extensions.colorBufferFloat)
2049 {
2050 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2051 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2052
2053 if (readFixedOrFloat != drawFixedOrFloat)
2054 {
Jamie Madill437fa652016-05-03 15:13:24 -04002055 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002056 "If the read buffer contains fixed-point or "
2057 "floating-point values, the draw buffer "
2058 "must as well."));
2059 return false;
2060 }
2061 }
2062 else if (readFixedPoint != drawFixedPoint)
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 "
2066 "values, the draw buffer must as well."));
2067 return false;
2068 }
2069
2070 if (readComponentType == GL_UNSIGNED_INT &&
2071 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002072 {
Jamie Madill437fa652016-05-03 15:13:24 -04002073 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002074 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002075 }
2076
Jamie Madill6163c752015-12-07 16:32:59 -05002077 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002078 {
Jamie Madill437fa652016-05-03 15:13:24 -04002079 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002080 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002081 }
2082
Jamie Madilla3944d42016-07-22 22:13:26 -04002083 if (readColorBuffer->getSamples() > 0 &&
2084 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002085 {
Jamie Madill437fa652016-05-03 15:13:24 -04002086 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002087 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002088 }
2089 }
2090 }
2091
Jamie Madilla3944d42016-07-22 22:13:26 -04002092 if ((readFormat.info->componentType == GL_INT ||
2093 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2094 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002095 {
Jamie Madill437fa652016-05-03 15:13:24 -04002096 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002097 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002098 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002099 }
He Yunchao66a41a22016-12-15 16:45:05 +08002100 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2101 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2102 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2103 // situation is an application error that would lead to a crash in ANGLE.
2104 else if (drawFramebuffer->hasEnabledDrawBuffer())
2105 {
2106 context->handleError(Error(
2107 GL_INVALID_OPERATION,
2108 "Attempt to read from a missing color attachment of a complete framebuffer."));
2109 return false;
2110 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002111 }
2112
He Yunchaoced53ae2016-11-29 15:00:51 +08002113 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002114 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2115 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002116 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002117 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002118 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002119 const gl::FramebufferAttachment *readBuffer =
2120 readFramebuffer->getAttachment(attachments[i]);
2121 const gl::FramebufferAttachment *drawBuffer =
2122 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002123
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002124 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002125 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002126 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002127 {
Jamie Madill437fa652016-05-03 15:13:24 -04002128 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002129 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002130 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002131
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002132 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002133 {
Jamie Madill437fa652016-05-03 15:13:24 -04002134 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002135 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002136 }
2137 }
He Yunchao66a41a22016-12-15 16:45:05 +08002138 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2139 else if (drawBuffer)
2140 {
2141 context->handleError(Error(GL_INVALID_OPERATION,
2142 "Attempt to read from a missing depth/stencil "
2143 "attachment of a complete framebuffer."));
2144 return false;
2145 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002146 }
2147 }
2148
2149 return true;
2150}
2151
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002152bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002153 GLint x,
2154 GLint y,
2155 GLsizei width,
2156 GLsizei height,
2157 GLenum format,
2158 GLenum type,
2159 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002160{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002161 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2162}
2163
2164bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2165 GLint x,
2166 GLint y,
2167 GLsizei width,
2168 GLsizei height,
2169 GLenum format,
2170 GLenum type,
2171 GLsizei bufSize,
2172 GLsizei *length,
2173 GLvoid *pixels)
2174{
2175 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002176 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002177 return false;
2178 }
2179
Geoff Lang62fce5b2016-09-30 10:46:35 -04002180 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2181 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002182 {
Geoff Langb1196682014-07-23 13:47:29 -04002183 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002184 }
2185
Geoff Lang62fce5b2016-09-30 10:46:35 -04002186 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002187 {
Geoff Langb1196682014-07-23 13:47:29 -04002188 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002189 }
2190
Jamie Madillc29968b2016-01-20 11:17:23 -05002191 return true;
2192}
2193
2194bool ValidateReadnPixelsEXT(Context *context,
2195 GLint x,
2196 GLint y,
2197 GLsizei width,
2198 GLsizei height,
2199 GLenum format,
2200 GLenum type,
2201 GLsizei bufSize,
2202 GLvoid *pixels)
2203{
2204 if (bufSize < 0)
2205 {
Jamie Madill437fa652016-05-03 15:13:24 -04002206 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002207 return false;
2208 }
2209
Geoff Lang62fce5b2016-09-30 10:46:35 -04002210 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2211 pixels);
2212}
Jamie Madill26e91952014-03-05 15:01:27 -05002213
Geoff Lang62fce5b2016-09-30 10:46:35 -04002214bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2215 GLint x,
2216 GLint y,
2217 GLsizei width,
2218 GLsizei height,
2219 GLenum format,
2220 GLenum type,
2221 GLsizei bufSize,
2222 GLsizei *length,
2223 GLvoid *data)
2224{
2225 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002226 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002227 return false;
2228 }
2229
Geoff Lang62fce5b2016-09-30 10:46:35 -04002230 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002231 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002232 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002233 }
2234
Geoff Lang62fce5b2016-09-30 10:46:35 -04002235 if (!ValidateRobustBufferSize(context, bufSize, *length))
2236 {
2237 return false;
2238 }
2239
2240 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002241}
2242
Olli Etuaho41997e72016-03-10 13:38:39 +02002243bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002244{
2245 if (!context->getExtensions().occlusionQueryBoolean &&
2246 !context->getExtensions().disjointTimerQuery)
2247 {
Jamie Madill437fa652016-05-03 15:13:24 -04002248 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002249 return false;
2250 }
2251
Olli Etuaho41997e72016-03-10 13:38:39 +02002252 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002253}
2254
Olli Etuaho41997e72016-03-10 13:38:39 +02002255bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002256{
2257 if (!context->getExtensions().occlusionQueryBoolean &&
2258 !context->getExtensions().disjointTimerQuery)
2259 {
Jamie Madill437fa652016-05-03 15:13:24 -04002260 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002261 return false;
2262 }
2263
Olli Etuaho41997e72016-03-10 13:38:39 +02002264 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002265}
2266
2267bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002268{
2269 if (!ValidQueryType(context, target))
2270 {
Jamie Madill437fa652016-05-03 15:13:24 -04002271 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002272 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002273 }
2274
2275 if (id == 0)
2276 {
Jamie Madill437fa652016-05-03 15:13:24 -04002277 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002278 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002279 }
2280
2281 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2282 // of zero, if the active query object name for <target> is non-zero (for the
2283 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2284 // the active query for either target is non-zero), if <id> is the name of an
2285 // existing query object whose type does not match <target>, or if <id> is the
2286 // active query object name for any query type, the error INVALID_OPERATION is
2287 // generated.
2288
2289 // Ensure no other queries are active
2290 // NOTE: If other queries than occlusion are supported, we will need to check
2291 // separately that:
2292 // a) The query ID passed is not the current active query for any target/type
2293 // b) There are no active queries for the requested target (and in the case
2294 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2295 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002296
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002297 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002298 {
Jamie Madill437fa652016-05-03 15:13:24 -04002299 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002300 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002301 }
2302
2303 Query *queryObject = context->getQuery(id, true, target);
2304
2305 // check that name was obtained with glGenQueries
2306 if (!queryObject)
2307 {
Jamie Madill437fa652016-05-03 15:13:24 -04002308 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002309 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002310 }
2311
2312 // check for type mismatch
2313 if (queryObject->getType() != target)
2314 {
Jamie Madill437fa652016-05-03 15:13:24 -04002315 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002316 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002317 }
2318
2319 return true;
2320}
2321
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002322bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2323{
2324 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002325 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002326 {
Jamie Madill437fa652016-05-03 15:13:24 -04002327 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002328 return false;
2329 }
2330
2331 return ValidateBeginQueryBase(context, target, id);
2332}
2333
2334bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002335{
2336 if (!ValidQueryType(context, target))
2337 {
Jamie Madill437fa652016-05-03 15:13:24 -04002338 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002339 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002340 }
2341
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002342 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002343
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002344 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002345 {
Jamie Madill437fa652016-05-03 15:13:24 -04002346 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002347 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002348 }
2349
Jamie Madill45c785d2014-05-13 14:09:34 -04002350 return true;
2351}
2352
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002353bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2354{
2355 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002356 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002357 {
Jamie Madill437fa652016-05-03 15:13:24 -04002358 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002359 return false;
2360 }
2361
2362 return ValidateEndQueryBase(context, target);
2363}
2364
2365bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2366{
2367 if (!context->getExtensions().disjointTimerQuery)
2368 {
Jamie Madill437fa652016-05-03 15:13:24 -04002369 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002370 return false;
2371 }
2372
2373 if (target != GL_TIMESTAMP_EXT)
2374 {
Jamie Madill437fa652016-05-03 15:13:24 -04002375 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002376 return false;
2377 }
2378
2379 Query *queryObject = context->getQuery(id, true, target);
2380 if (queryObject == nullptr)
2381 {
Jamie Madill437fa652016-05-03 15:13:24 -04002382 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002383 return false;
2384 }
2385
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002386 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002387 {
Jamie Madill437fa652016-05-03 15:13:24 -04002388 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002389 return false;
2390 }
2391
2392 return true;
2393}
2394
Geoff Lang2186c382016-10-14 10:54:54 -04002395bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002396{
Geoff Lang2186c382016-10-14 10:54:54 -04002397 if (numParams)
2398 {
2399 *numParams = 0;
2400 }
2401
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002402 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2403 {
Jamie Madill437fa652016-05-03 15:13:24 -04002404 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002405 return false;
2406 }
2407
2408 switch (pname)
2409 {
2410 case GL_CURRENT_QUERY_EXT:
2411 if (target == GL_TIMESTAMP_EXT)
2412 {
Jamie Madill437fa652016-05-03 15:13:24 -04002413 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002414 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2415 return false;
2416 }
2417 break;
2418 case GL_QUERY_COUNTER_BITS_EXT:
2419 if (!context->getExtensions().disjointTimerQuery ||
2420 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2421 {
Jamie Madill437fa652016-05-03 15:13:24 -04002422 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002423 return false;
2424 }
2425 break;
2426 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002427 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002428 return false;
2429 }
2430
Geoff Lang2186c382016-10-14 10:54:54 -04002431 if (numParams)
2432 {
2433 // All queries return only one value
2434 *numParams = 1;
2435 }
2436
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002437 return true;
2438}
2439
2440bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2441{
2442 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002443 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002444 {
Jamie Madill437fa652016-05-03 15:13:24 -04002445 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002446 return false;
2447 }
2448
Geoff Lang2186c382016-10-14 10:54:54 -04002449 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002450}
2451
Geoff Lang2186c382016-10-14 10:54:54 -04002452bool ValidateGetQueryivRobustANGLE(Context *context,
2453 GLenum target,
2454 GLenum pname,
2455 GLsizei bufSize,
2456 GLsizei *length,
2457 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002458{
Geoff Lang2186c382016-10-14 10:54:54 -04002459 if (!ValidateRobustEntryPoint(context, bufSize))
2460 {
2461 return false;
2462 }
2463
2464 if (!ValidateGetQueryivBase(context, target, pname, length))
2465 {
2466 return false;
2467 }
2468
2469 if (!ValidateRobustBufferSize(context, bufSize, *length))
2470 {
2471 return false;
2472 }
2473
2474 return true;
2475}
2476
2477bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2478{
2479 if (numParams)
2480 {
2481 *numParams = 0;
2482 }
2483
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002484 Query *queryObject = context->getQuery(id, false, GL_NONE);
2485
2486 if (!queryObject)
2487 {
Jamie Madill437fa652016-05-03 15:13:24 -04002488 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002489 return false;
2490 }
2491
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002492 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002493 {
Jamie Madill437fa652016-05-03 15:13:24 -04002494 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002495 return false;
2496 }
2497
2498 switch (pname)
2499 {
2500 case GL_QUERY_RESULT_EXT:
2501 case GL_QUERY_RESULT_AVAILABLE_EXT:
2502 break;
2503
2504 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002505 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002506 return false;
2507 }
2508
Geoff Lang2186c382016-10-14 10:54:54 -04002509 if (numParams)
2510 {
2511 *numParams = 1;
2512 }
2513
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002514 return true;
2515}
2516
2517bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2518{
2519 if (!context->getExtensions().disjointTimerQuery)
2520 {
Jamie Madill437fa652016-05-03 15:13:24 -04002521 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002522 return false;
2523 }
Geoff Lang2186c382016-10-14 10:54:54 -04002524 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2525}
2526
2527bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2528 GLuint id,
2529 GLenum pname,
2530 GLsizei bufSize,
2531 GLsizei *length,
2532 GLint *params)
2533{
2534 if (!context->getExtensions().disjointTimerQuery)
2535 {
2536 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2537 return false;
2538 }
2539
2540 if (!ValidateRobustEntryPoint(context, bufSize))
2541 {
2542 return false;
2543 }
2544
2545 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2546 {
2547 return false;
2548 }
2549
2550 if (!ValidateRobustBufferSize(context, bufSize, *length))
2551 {
2552 return false;
2553 }
2554
2555 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002556}
2557
2558bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2559{
2560 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002561 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002562 {
Jamie Madill437fa652016-05-03 15:13:24 -04002563 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002564 return false;
2565 }
Geoff Lang2186c382016-10-14 10:54:54 -04002566 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2567}
2568
2569bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2570 GLuint id,
2571 GLenum pname,
2572 GLsizei bufSize,
2573 GLsizei *length,
2574 GLuint *params)
2575{
2576 if (!context->getExtensions().disjointTimerQuery &&
2577 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2578 {
2579 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2580 return false;
2581 }
2582
2583 if (!ValidateRobustEntryPoint(context, bufSize))
2584 {
2585 return false;
2586 }
2587
2588 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2589 {
2590 return false;
2591 }
2592
2593 if (!ValidateRobustBufferSize(context, bufSize, *length))
2594 {
2595 return false;
2596 }
2597
2598 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002599}
2600
2601bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2602{
2603 if (!context->getExtensions().disjointTimerQuery)
2604 {
Jamie Madill437fa652016-05-03 15:13:24 -04002605 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002606 return false;
2607 }
Geoff Lang2186c382016-10-14 10:54:54 -04002608 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2609}
2610
2611bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2612 GLuint id,
2613 GLenum pname,
2614 GLsizei bufSize,
2615 GLsizei *length,
2616 GLint64 *params)
2617{
2618 if (!context->getExtensions().disjointTimerQuery)
2619 {
2620 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2621 return false;
2622 }
2623
2624 if (!ValidateRobustEntryPoint(context, bufSize))
2625 {
2626 return false;
2627 }
2628
2629 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2630 {
2631 return false;
2632 }
2633
2634 if (!ValidateRobustBufferSize(context, bufSize, *length))
2635 {
2636 return false;
2637 }
2638
2639 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002640}
2641
2642bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2643{
2644 if (!context->getExtensions().disjointTimerQuery)
2645 {
Jamie Madill437fa652016-05-03 15:13:24 -04002646 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002647 return false;
2648 }
Geoff Lang2186c382016-10-14 10:54:54 -04002649 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2650}
2651
2652bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2653 GLuint id,
2654 GLenum pname,
2655 GLsizei bufSize,
2656 GLsizei *length,
2657 GLuint64 *params)
2658{
2659 if (!context->getExtensions().disjointTimerQuery)
2660 {
2661 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2662 return false;
2663 }
2664
2665 if (!ValidateRobustEntryPoint(context, bufSize))
2666 {
2667 return false;
2668 }
2669
2670 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2671 {
2672 return false;
2673 }
2674
2675 if (!ValidateRobustBufferSize(context, bufSize, *length))
2676 {
2677 return false;
2678 }
2679
2680 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002681}
2682
Jamie Madill62d31cb2015-09-11 13:25:51 -04002683static bool ValidateUniformCommonBase(gl::Context *context,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002684 gl::Program *program,
Jamie Madill62d31cb2015-09-11 13:25:51 -04002685 GLenum targetUniformType,
2686 GLint location,
2687 GLsizei count,
2688 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002689{
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002690 // TODO(Jiajia): Add image uniform check in future.
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002691 if (count < 0)
2692 {
Jamie Madill437fa652016-05-03 15:13:24 -04002693 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002694 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002695 }
2696
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002697 if (!program || !program->isLinked())
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002698 {
Jamie Madill437fa652016-05-03 15:13:24 -04002699 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002700 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002701 }
2702
Jamie Madillac4e9c32017-01-13 14:07:12 -05002703 if (location == -1)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002704 {
2705 // Silently ignore the uniform command
2706 return false;
2707 }
2708
Jamie Madillac4e9c32017-01-13 14:07:12 -05002709 const auto &uniformLocations = program->getUniformLocations();
2710 size_t castedLocation = static_cast<size_t>(location);
2711 if (castedLocation >= uniformLocations.size())
2712 {
2713 context->handleError(Error(GL_INVALID_OPERATION, "Invalid uniform location"));
2714 return false;
2715 }
2716
2717 const auto &uniformLocation = uniformLocations[castedLocation];
2718 if (uniformLocation.ignored)
2719 {
2720 // Silently ignore the uniform command
2721 return false;
2722 }
2723
2724 if (!uniformLocation.used)
Jamie Madill36398922014-05-20 14:51:53 -04002725 {
Jamie Madill437fa652016-05-03 15:13:24 -04002726 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002727 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002728 }
2729
Jamie Madillac4e9c32017-01-13 14:07:12 -05002730 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
Jamie Madill36398922014-05-20 14:51:53 -04002731
2732 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002733 if (!uniform.isArray() && count > 1)
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 Madill62d31cb2015-09-11 13:25:51 -04002739 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002740 return true;
2741}
2742
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002743bool ValidateProgramUniform(gl::Context *context,
2744 GLenum uniformType,
2745 GLuint program,
2746 GLint location,
2747 GLsizei count)
2748{
2749 // Check for ES31 program uniform entry points
2750 if (context->getClientVersion() < Version(3, 1))
2751 {
2752 context->handleError(Error(GL_INVALID_OPERATION));
2753 return false;
2754 }
2755
2756 const LinkedUniform *uniform = nullptr;
2757 gl::Program *programObject = GetValidProgram(context, program);
2758 if (!ValidateUniformCommonBase(context, programObject, uniformType, location, count, &uniform))
2759 {
2760 return false;
2761 }
2762
2763 GLenum targetBoolType = VariableBoolVectorType(uniformType);
2764 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
2765 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2766 {
2767 context->handleError(Error(GL_INVALID_OPERATION));
2768 return false;
2769 }
2770
2771 return true;
2772}
2773
2774bool ValidateProgramUniformMatrix(gl::Context *context,
2775 GLenum matrixType,
2776 GLuint program,
2777 GLint location,
2778 GLsizei count,
2779 GLboolean transpose)
2780{
2781 // Check for ES31 program uniform entry points
2782 if (context->getClientVersion() < Version(3, 1))
2783 {
2784 context->handleError(Error(GL_INVALID_OPERATION));
2785 return false;
2786 }
2787
2788 const LinkedUniform *uniform = nullptr;
2789 gl::Program *programObject = GetValidProgram(context, program);
2790 if (!ValidateUniformCommonBase(context, programObject, matrixType, location, count, &uniform))
2791 {
2792 return false;
2793 }
2794
2795 if (uniform->type != matrixType)
2796 {
2797 context->handleError(Error(GL_INVALID_OPERATION));
2798 return false;
2799 }
2800
2801 return true;
2802}
2803
Jamie Madillaa981bd2014-05-20 10:55:55 -04002804bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2805{
2806 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002807 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2808 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002809 {
Jamie Madill437fa652016-05-03 15:13:24 -04002810 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002811 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002812 }
2813
Jamie Madill62d31cb2015-09-11 13:25:51 -04002814 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002815 gl::Program *program = context->getGLState().getProgram();
2816 if (!ValidateUniformCommonBase(context, program, uniformType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002817 {
2818 return false;
2819 }
2820
He Yunchaoced53ae2016-11-29 15:00:51 +08002821 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002822 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002823 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2824 {
Jamie Madill437fa652016-05-03 15:13:24 -04002825 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002826 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002827 }
2828
2829 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002830}
2831
He Yunchaoced53ae2016-11-29 15:00:51 +08002832bool ValidateUniformMatrix(gl::Context *context,
2833 GLenum matrixType,
2834 GLint location,
2835 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002836 GLboolean transpose)
2837{
2838 // Check for ES3 uniform entry points
2839 int rows = VariableRowCount(matrixType);
2840 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002841 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002842 {
Jamie Madill437fa652016-05-03 15:13:24 -04002843 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002844 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002845 }
2846
Martin Radev1be913c2016-07-11 17:59:16 +03002847 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002848 {
Jamie Madill437fa652016-05-03 15:13:24 -04002849 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002850 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002851 }
2852
Jamie Madill62d31cb2015-09-11 13:25:51 -04002853 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002854 gl::Program *program = context->getGLState().getProgram();
2855 if (!ValidateUniformCommonBase(context, program, matrixType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002856 {
2857 return false;
2858 }
2859
2860 if (uniform->type != matrixType)
2861 {
Jamie Madill437fa652016-05-03 15:13:24 -04002862 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002863 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002864 }
2865
2866 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002867}
2868
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002869bool ValidateStateQuery(ValidationContext *context,
2870 GLenum pname,
2871 GLenum *nativeType,
2872 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002873{
2874 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2875 {
Jamie Madill437fa652016-05-03 15:13:24 -04002876 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002877 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002878 }
2879
Jamie Madill0af26e12015-03-05 19:54:33 -05002880 const Caps &caps = context->getCaps();
2881
Jamie Madill893ab082014-05-16 16:56:10 -04002882 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2883 {
2884 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2885
Jamie Madill0af26e12015-03-05 19:54:33 -05002886 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002887 {
Jamie Madill437fa652016-05-03 15:13:24 -04002888 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002889 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002890 }
2891 }
2892
2893 switch (pname)
2894 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002895 case GL_TEXTURE_BINDING_2D:
2896 case GL_TEXTURE_BINDING_CUBE_MAP:
2897 case GL_TEXTURE_BINDING_3D:
2898 case GL_TEXTURE_BINDING_2D_ARRAY:
2899 break;
2900 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2901 if (!context->getExtensions().eglStreamConsumerExternal &&
2902 !context->getExtensions().eglImageExternal)
2903 {
2904 context->handleError(Error(GL_INVALID_ENUM,
2905 "Neither NV_EGL_stream_consumer_external nor "
2906 "GL_OES_EGL_image_external extensions enabled"));
2907 return false;
2908 }
2909 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002910
He Yunchaoced53ae2016-11-29 15:00:51 +08002911 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2912 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002913 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002914 if (context->getGLState().getReadFramebuffer()->checkStatus(
2915 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002916 {
Jamie Madill437fa652016-05-03 15:13:24 -04002917 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002918 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002919 }
2920
Jamie Madill51f40ec2016-06-15 14:06:00 -04002921 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2922 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002923
2924 if (framebuffer->getReadBufferState() == GL_NONE)
2925 {
2926 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2927 return false;
2928 }
2929
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002930 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002931 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002932 {
Jamie Madill437fa652016-05-03 15:13:24 -04002933 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002934 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002935 }
2936 }
2937 break;
2938
He Yunchaoced53ae2016-11-29 15:00:51 +08002939 default:
2940 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002941 }
2942
2943 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002944 if (*numParams == 0)
2945 {
2946 return false;
2947 }
2948
2949 return true;
2950}
2951
2952bool ValidateRobustStateQuery(ValidationContext *context,
2953 GLenum pname,
2954 GLsizei bufSize,
2955 GLenum *nativeType,
2956 unsigned int *numParams)
2957{
2958 if (!ValidateRobustEntryPoint(context, bufSize))
2959 {
2960 return false;
2961 }
2962
2963 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2964 {
2965 return false;
2966 }
2967
2968 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002969 {
2970 return false;
2971 }
2972
2973 return true;
2974}
2975
Jamie Madillc29968b2016-01-20 11:17:23 -05002976bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2977 GLenum target,
2978 GLint level,
2979 GLenum internalformat,
2980 bool isSubImage,
2981 GLint xoffset,
2982 GLint yoffset,
2983 GLint zoffset,
2984 GLint x,
2985 GLint y,
2986 GLsizei width,
2987 GLsizei height,
2988 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002989 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002990{
Jamie Madill560a8d82014-05-21 13:06:20 -04002991 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2992 {
Jamie Madill437fa652016-05-03 15:13:24 -04002993 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002994 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002995 }
2996
He Yunchaoced53ae2016-11-29 15:00:51 +08002997 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2998 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002999 {
Jamie Madill437fa652016-05-03 15:13:24 -04003000 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003001 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003002 }
3003
3004 if (border != 0)
3005 {
Jamie Madill437fa652016-05-03 15:13:24 -04003006 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003007 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003008 }
3009
3010 if (!ValidMipLevel(context, target, level))
3011 {
Jamie Madill437fa652016-05-03 15:13:24 -04003012 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003013 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003014 }
3015
Jamie Madill51f40ec2016-06-15 14:06:00 -04003016 const auto &state = context->getGLState();
3017 auto readFramebuffer = state.getReadFramebuffer();
3018 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04003019 {
Jamie Madill437fa652016-05-03 15:13:24 -04003020 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003021 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003022 }
3023
Jamie Madill51f40ec2016-06-15 14:06:00 -04003024 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003025 {
Jamie Madill437fa652016-05-03 15:13:24 -04003026 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003027 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003028 }
3029
Martin Radev138064f2016-07-15 12:03:41 +03003030 if (readFramebuffer->getReadBufferState() == GL_NONE)
3031 {
3032 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
3033 return false;
3034 }
3035
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003036 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
3037 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003038 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003039 // situation is an application error that would lead to a crash in ANGLE.
3040 if (readFramebuffer->getReadColorbuffer() == nullptr)
3041 {
3042 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3043 return false;
3044 }
3045
Geoff Langaae65a42014-05-26 12:43:44 -04003046 const gl::Caps &caps = context->getCaps();
3047
Geoff Langaae65a42014-05-26 12:43:44 -04003048 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003049 switch (target)
3050 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003051 case GL_TEXTURE_2D:
3052 maxDimension = caps.max2DTextureSize;
3053 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003054
He Yunchaoced53ae2016-11-29 15:00:51 +08003055 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3056 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3057 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3058 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3059 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3060 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3061 maxDimension = caps.maxCubeMapTextureSize;
3062 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003063
He Yunchaoced53ae2016-11-29 15:00:51 +08003064 case GL_TEXTURE_2D_ARRAY:
3065 maxDimension = caps.max2DTextureSize;
3066 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003067
He Yunchaoced53ae2016-11-29 15:00:51 +08003068 case GL_TEXTURE_3D:
3069 maxDimension = caps.max3DTextureSize;
3070 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003071
He Yunchaoced53ae2016-11-29 15:00:51 +08003072 default:
3073 context->handleError(Error(GL_INVALID_ENUM));
3074 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003075 }
3076
Jamie Madillc29968b2016-01-20 11:17:23 -05003077 gl::Texture *texture =
3078 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003079 if (!texture)
3080 {
Jamie Madill437fa652016-05-03 15:13:24 -04003081 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003082 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003083 }
3084
Geoff Lang69cce582015-09-17 13:20:36 -04003085 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003086 {
Jamie Madill437fa652016-05-03 15:13:24 -04003087 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003088 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003089 }
3090
Geoff Lang5d601382014-07-22 15:14:06 -04003091 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3092
3093 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003094 {
Jamie Madill437fa652016-05-03 15:13:24 -04003095 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003096 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003097 }
3098
Geoff Langa9be0dc2014-12-17 12:34:40 -05003099 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003100 {
Jamie Madill437fa652016-05-03 15:13:24 -04003101 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003102 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003103 }
3104
3105 if (isSubImage)
3106 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003107 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3108 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3109 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003110 {
Jamie Madill437fa652016-05-03 15:13:24 -04003111 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003112 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003113 }
3114 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003115 else
3116 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003117 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003118 {
Jamie Madill437fa652016-05-03 15:13:24 -04003119 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003120 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003121 }
3122
Geoff Langeb66a6e2016-10-31 13:06:12 -04003123 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003124 {
Jamie Madill437fa652016-05-03 15:13:24 -04003125 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003126 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003127 }
3128
3129 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003130 if (static_cast<int>(width) > maxLevelDimension ||
3131 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003132 {
Jamie Madill437fa652016-05-03 15:13:24 -04003133 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003134 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003135 }
3136 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003137
Jamie Madill0c8abca2016-07-22 20:21:26 -04003138 if (textureFormatOut)
3139 {
3140 *textureFormatOut = texture->getFormat(target, level);
3141 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05003142
3143 // Detect texture copying feedback loops for WebGL.
3144 if (context->getExtensions().webglCompatibility)
3145 {
3146 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level))
3147 {
3148 context->handleError(Error(GL_INVALID_OPERATION,
3149 "Texture copying feedback loop formed between Framebuffer "
3150 "and specified Texture level."));
3151 return false;
3152 }
3153 }
3154
Jamie Madill560a8d82014-05-21 13:06:20 -04003155 return true;
3156}
3157
Jiajia Qind9671222016-11-29 16:30:31 +08003158bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003159{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003160 switch (mode)
3161 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003162 case GL_POINTS:
3163 case GL_LINES:
3164 case GL_LINE_LOOP:
3165 case GL_LINE_STRIP:
3166 case GL_TRIANGLES:
3167 case GL_TRIANGLE_STRIP:
3168 case GL_TRIANGLE_FAN:
3169 break;
3170 default:
3171 context->handleError(Error(GL_INVALID_ENUM));
3172 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003173 }
3174
Jamie Madill250d33f2014-06-06 17:09:03 -04003175 if (count < 0)
3176 {
Jamie Madill437fa652016-05-03 15:13:24 -04003177 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003178 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003179 }
3180
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003181 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003182
Jamie Madill250d33f2014-06-06 17:09:03 -04003183 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003184 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003185 {
Jamie Madill437fa652016-05-03 15:13:24 -04003186 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003187 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003188 }
3189
Jamie Madillcbcde722017-01-06 14:50:00 -05003190 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3191 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003192 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003193 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3194 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003195 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003196 const FramebufferAttachment *dsAttachment =
3197 framebuffer->getStencilOrDepthStencilAttachment();
3198 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003199 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003200 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003201
3202 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3203 bool differentWritemasks =
3204 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3205 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3206 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3207 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3208
3209 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003210 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003211 if (!context->getExtensions().webglCompatibility)
3212 {
Jamie Madill6a6b09c2017-01-12 21:52:29 +00003213 ERR("This ANGLE implementation does not support separate front/back stencil "
3214 "writemasks, reference values, or stencil mask values.");
Jamie Madillcbcde722017-01-06 14:50:00 -05003215 }
Jamie Madill437fa652016-05-03 15:13:24 -04003216 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003217 return false;
3218 }
Jamie Madillac528012014-06-20 13:21:23 -04003219 }
3220
Jamie Madill51f40ec2016-06-15 14:06:00 -04003221 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003222 {
Jamie Madill437fa652016-05-03 15:13:24 -04003223 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003224 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003225 }
3226
Geoff Lang7dd2e102014-11-10 15:19:26 -05003227 gl::Program *program = state.getProgram();
3228 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003229 {
Jamie Madill437fa652016-05-03 15:13:24 -04003230 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003231 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003232 }
3233
Geoff Lang7dd2e102014-11-10 15:19:26 -05003234 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003235 {
Jamie Madill437fa652016-05-03 15:13:24 -04003236 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003237 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003238 }
3239
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003240 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003241 for (unsigned int uniformBlockIndex = 0;
3242 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003243 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003244 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003245 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003246 const OffsetBindingPointer<Buffer> &uniformBuffer =
3247 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003248
Geoff Lang5d124a62015-09-15 13:03:27 -04003249 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003250 {
3251 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003252 context->handleError(
3253 Error(GL_INVALID_OPERATION,
3254 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003255 return false;
3256 }
3257
Geoff Lang5d124a62015-09-15 13:03:27 -04003258 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003259 if (uniformBufferSize == 0)
3260 {
3261 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003262 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003263 }
3264
Jamie Madill62d31cb2015-09-11 13:25:51 -04003265 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003266 {
3267 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003268 context->handleError(
3269 Error(GL_INVALID_OPERATION,
3270 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003271 return false;
3272 }
3273 }
3274
Jamie Madilla4595b82017-01-11 17:36:34 -05003275 // Detect rendering feedback loops for WebGL.
3276 if (context->getExtensions().webglCompatibility)
3277 {
3278 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3279 {
3280 context->handleError(
3281 Error(GL_INVALID_OPERATION,
3282 "Rendering feedback loop formed between Framebuffer and active Texture."));
3283 return false;
3284 }
3285 }
3286
Jamie Madill250d33f2014-06-06 17:09:03 -04003287 // No-op if zero count
3288 return (count > 0);
3289}
3290
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003291bool ValidateDrawArrays(ValidationContext *context,
3292 GLenum mode,
3293 GLint first,
3294 GLsizei count,
3295 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003296{
Jamie Madillfd716582014-06-06 17:09:04 -04003297 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003298 {
Jamie Madill437fa652016-05-03 15:13:24 -04003299 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003300 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003301 }
3302
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003303 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003304 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003305 if (curTransformFeedback && curTransformFeedback->isActive() &&
3306 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003307 {
3308 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003309 // that does not match the current transform feedback object's draw mode (if transform
3310 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003311 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003312 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003313 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003314 }
3315
Jiajia Qind9671222016-11-29 16:30:31 +08003316 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003317 {
3318 return false;
3319 }
3320
Corentin Wallez71168a02016-12-19 15:11:18 -08003321 // Check the computation of maxVertex doesn't overflow.
3322 // - first < 0 or count < 0 have been checked as an error condition
3323 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3324 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3325 ASSERT(count > 0 && first >= 0);
3326 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3327 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003328 {
3329 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3330 return false;
3331 }
3332
Corentin Wallez71168a02016-12-19 15:11:18 -08003333 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003334 {
3335 return false;
3336 }
3337
3338 return true;
3339}
3340
He Yunchaoced53ae2016-11-29 15:00:51 +08003341bool ValidateDrawArraysInstanced(Context *context,
3342 GLenum mode,
3343 GLint first,
3344 GLsizei count,
3345 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003346{
3347 if (primcount < 0)
3348 {
Jamie Madill437fa652016-05-03 15:13:24 -04003349 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003350 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003351 }
3352
Jamie Madill2b976812014-08-25 15:47:49 -04003353 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003354 {
3355 return false;
3356 }
3357
3358 // No-op if zero primitive count
3359 return (primcount > 0);
3360}
3361
Geoff Lang87a93302014-09-16 13:29:43 -04003362static bool ValidateDrawInstancedANGLE(Context *context)
3363{
3364 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003365 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003366
Geoff Lang7dd2e102014-11-10 15:19:26 -05003367 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003368
3369 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003370 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003371 {
3372 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003373 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003374 {
3375 return true;
3376 }
3377 }
3378
Jamie Madill437fa652016-05-03 15:13:24 -04003379 context->handleError(Error(GL_INVALID_OPERATION,
3380 "ANGLE_instanced_arrays requires that at least one active attribute"
3381 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003382 return false;
3383}
3384
He Yunchaoced53ae2016-11-29 15:00:51 +08003385bool ValidateDrawArraysInstancedANGLE(Context *context,
3386 GLenum mode,
3387 GLint first,
3388 GLsizei count,
3389 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003390{
3391 if (!ValidateDrawInstancedANGLE(context))
3392 {
3393 return false;
3394 }
3395
3396 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3397}
3398
Jiajia Qind9671222016-11-29 16:30:31 +08003399bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003400{
Jamie Madill250d33f2014-06-06 17:09:03 -04003401 switch (type)
3402 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003403 case GL_UNSIGNED_BYTE:
3404 case GL_UNSIGNED_SHORT:
3405 break;
3406 case GL_UNSIGNED_INT:
3407 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3408 {
3409 context->handleError(Error(GL_INVALID_ENUM));
3410 return false;
3411 }
3412 break;
3413 default:
3414 context->handleError(Error(GL_INVALID_ENUM));
3415 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003416 }
3417
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003418 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003419
3420 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003421 if (curTransformFeedback && curTransformFeedback->isActive() &&
3422 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003423 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003424 // It is an invalid operation to call DrawElements, DrawRangeElements or
3425 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003426 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003427 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003428 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003429 }
3430
Jiajia Qind9671222016-11-29 16:30:31 +08003431 return true;
3432}
3433
3434bool ValidateDrawElements(ValidationContext *context,
3435 GLenum mode,
3436 GLsizei count,
3437 GLenum type,
3438 const GLvoid *indices,
3439 GLsizei primcount,
3440 IndexRange *indexRangeOut)
3441{
3442 if (!ValidateDrawElementsBase(context, type))
3443 return false;
3444
3445 const State &state = context->getGLState();
3446
Jamie Madill250d33f2014-06-06 17:09:03 -04003447 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003448 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003449 {
Jamie Madill437fa652016-05-03 15:13:24 -04003450 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003451 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003452 }
3453
He Yunchaoced53ae2016-11-29 15:00:51 +08003454 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003455 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003456
Jamie Madillae3000b2014-08-25 15:47:51 -04003457 if (elementArrayBuffer)
3458 {
3459 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3460
3461 GLint64 offset = reinterpret_cast<GLint64>(indices);
He Yunchaoced53ae2016-11-29 15:00:51 +08003462 GLint64 byteCount =
3463 static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count) + offset;
Jamie Madillae3000b2014-08-25 15:47:51 -04003464
3465 // check for integer overflows
3466 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3467 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3468 {
Jamie Madill437fa652016-05-03 15:13:24 -04003469 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003470 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003471 }
3472
3473 // Check for reading past the end of the bound buffer object
3474 if (byteCount > elementArrayBuffer->getSize())
3475 {
Jamie Madill437fa652016-05-03 15:13:24 -04003476 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003477 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003478 }
3479 }
Corentin Wallez327411e2016-12-09 11:09:17 -05003480 else if (context->getExtensions().webglCompatibility && 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(
3486 Error(GL_INVALID_OPERATION, "There is no element array buffer bound and count > 0."));
3487 return false;
3488 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003489 else if (!indices)
3490 {
Corentin Wallez327411e2016-12-09 11:09:17 -05003491 // This is an application error that would normally result in a crash,
3492 // but we catch it and return an error
3493 context->handleError(
3494 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003495 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003496 }
3497
Jiajia Qind9671222016-11-29 16:30:31 +08003498 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003499 {
3500 return false;
3501 }
3502
Jamie Madill2b976812014-08-25 15:47:49 -04003503 // Use max index to validate if our vertex buffers are large enough for the pull.
3504 // TODO: offer fast path, with disabled index validation.
3505 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3506 if (elementArrayBuffer)
3507 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003508 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003509 Error error =
3510 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3511 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003512 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003513 {
Jamie Madill437fa652016-05-03 15:13:24 -04003514 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003515 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003516 }
3517 }
3518 else
3519 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003520 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003521 }
3522
Jamie Madille79b1e12015-11-04 16:36:37 -05003523 // If we use an index greater than our maximum supported index range, return an error.
3524 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3525 // return an error if possible here.
3526 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3527 {
Jamie Madill437fa652016-05-03 15:13:24 -04003528 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003529 return false;
3530 }
3531
Corentin Wallez92db6942016-12-09 13:10:36 -05003532 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3533 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003534 {
3535 return false;
3536 }
3537
Geoff Lang3edfe032015-09-04 16:38:24 -04003538 // No op if there are no real indices in the index data (all are primitive restart).
3539 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003540}
3541
Geoff Langb1196682014-07-23 13:47:29 -04003542bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003543 GLenum mode,
3544 GLsizei count,
3545 GLenum type,
3546 const GLvoid *indices,
3547 GLsizei primcount,
3548 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003549{
3550 if (primcount < 0)
3551 {
Jamie Madill437fa652016-05-03 15:13:24 -04003552 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003553 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003554 }
3555
Jamie Madill2b976812014-08-25 15:47:49 -04003556 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003557 {
3558 return false;
3559 }
3560
3561 // No-op zero primitive count
3562 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003563}
3564
Geoff Lang3edfe032015-09-04 16:38:24 -04003565bool ValidateDrawElementsInstancedANGLE(Context *context,
3566 GLenum mode,
3567 GLsizei count,
3568 GLenum type,
3569 const GLvoid *indices,
3570 GLsizei primcount,
3571 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003572{
3573 if (!ValidateDrawInstancedANGLE(context))
3574 {
3575 return false;
3576 }
3577
He Yunchaoced53ae2016-11-29 15:00:51 +08003578 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3579 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003580}
3581
He Yunchaoced53ae2016-11-29 15:00:51 +08003582bool ValidateFramebufferTextureBase(Context *context,
3583 GLenum target,
3584 GLenum attachment,
3585 GLuint texture,
3586 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003587{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003588 if (!ValidFramebufferTarget(target))
3589 {
Jamie Madill437fa652016-05-03 15:13:24 -04003590 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003591 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003592 }
3593
3594 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003595 {
3596 return false;
3597 }
3598
Jamie Madill55ec3b12014-07-03 10:38:57 -04003599 if (texture != 0)
3600 {
3601 gl::Texture *tex = context->getTexture(texture);
3602
3603 if (tex == NULL)
3604 {
Jamie Madill437fa652016-05-03 15:13:24 -04003605 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003606 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003607 }
3608
3609 if (level < 0)
3610 {
Jamie Madill437fa652016-05-03 15:13:24 -04003611 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003612 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003613 }
3614 }
3615
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003616 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003617 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003618
Jamie Madill84115c92015-04-23 15:00:07 -04003619 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003620 {
Jamie Madill437fa652016-05-03 15:13:24 -04003621 context->handleError(
3622 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003623 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003624 }
3625
3626 return true;
3627}
3628
He Yunchaoced53ae2016-11-29 15:00:51 +08003629bool ValidateFramebufferTexture2D(Context *context,
3630 GLenum target,
3631 GLenum attachment,
3632 GLenum textarget,
3633 GLuint texture,
3634 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003635{
He Yunchaoced53ae2016-11-29 15:00:51 +08003636 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3637 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003638 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3639 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003640 {
Jamie Madill437fa652016-05-03 15:13:24 -04003641 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003642 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003643 }
3644
3645 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003646 {
3647 return false;
3648 }
3649
Jamie Madill55ec3b12014-07-03 10:38:57 -04003650 if (texture != 0)
3651 {
3652 gl::Texture *tex = context->getTexture(texture);
3653 ASSERT(tex);
3654
Jamie Madill2a6564e2014-07-11 09:53:19 -04003655 const gl::Caps &caps = context->getCaps();
3656
Jamie Madill55ec3b12014-07-03 10:38:57 -04003657 switch (textarget)
3658 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003659 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003660 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003661 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003662 {
Jamie Madill437fa652016-05-03 15:13:24 -04003663 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003664 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003665 }
3666 if (tex->getTarget() != GL_TEXTURE_2D)
3667 {
Jamie Madill437fa652016-05-03 15:13:24 -04003668 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003669 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003670 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003671 }
3672 break;
3673
He Yunchaoced53ae2016-11-29 15:00:51 +08003674 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3675 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3676 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3677 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3678 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3679 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003680 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003681 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003682 {
Jamie Madill437fa652016-05-03 15:13:24 -04003683 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003684 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003685 }
3686 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3687 {
Jamie Madill437fa652016-05-03 15:13:24 -04003688 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003689 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003690 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003691 }
3692 break;
3693
He Yunchaoced53ae2016-11-29 15:00:51 +08003694 default:
3695 context->handleError(Error(GL_INVALID_ENUM));
3696 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003697 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003698
Jamie Madilla3944d42016-07-22 22:13:26 -04003699 const Format &format = tex->getFormat(textarget, level);
3700 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003701 {
Jamie Madill437fa652016-05-03 15:13:24 -04003702 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003703 return false;
3704 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003705 }
3706
Jamie Madill570f7c82014-07-03 10:38:54 -04003707 return true;
3708}
3709
Geoff Langb1196682014-07-23 13:47:29 -04003710bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003711{
3712 if (program == 0)
3713 {
Jamie Madill437fa652016-05-03 15:13:24 -04003714 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003715 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003716 }
3717
Dian Xiang769769a2015-09-09 15:20:08 -07003718 gl::Program *programObject = GetValidProgram(context, program);
3719 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003720 {
3721 return false;
3722 }
3723
Jamie Madill0063c512014-08-25 15:47:53 -04003724 if (!programObject || !programObject->isLinked())
3725 {
Jamie Madill437fa652016-05-03 15:13:24 -04003726 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003727 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003728 }
3729
Geoff Lang7dd2e102014-11-10 15:19:26 -05003730 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003731 {
Jamie Madill437fa652016-05-03 15:13:24 -04003732 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003733 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003734 }
3735
Jamie Madill0063c512014-08-25 15:47:53 -04003736 return true;
3737}
3738
He Yunchaoced53ae2016-11-29 15:00:51 +08003739bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003740{
3741 return ValidateGetUniformBase(context, program, location);
3742}
3743
He Yunchaoced53ae2016-11-29 15:00:51 +08003744bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003745{
Jamie Madill78f41802014-08-25 15:47:55 -04003746 return ValidateGetUniformBase(context, program, location);
3747}
3748
Geoff Langf41d0ee2016-10-07 13:04:23 -04003749static bool ValidateSizedGetUniform(Context *context,
3750 GLuint program,
3751 GLint location,
3752 GLsizei bufSize,
3753 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003754{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003755 if (length)
3756 {
3757 *length = 0;
3758 }
3759
Jamie Madill78f41802014-08-25 15:47:55 -04003760 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003761 {
Jamie Madill78f41802014-08-25 15:47:55 -04003762 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003763 }
3764
Geoff Langf41d0ee2016-10-07 13:04:23 -04003765 if (bufSize < 0)
3766 {
3767 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3768 return false;
3769 }
3770
Jamie Madilla502c742014-08-28 17:19:13 -04003771 gl::Program *programObject = context->getProgram(program);
3772 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003773
Jamie Madill78f41802014-08-25 15:47:55 -04003774 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003775 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003776 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003777 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003778 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003779 context->handleError(
3780 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003781 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003782 }
3783
Geoff Langf41d0ee2016-10-07 13:04:23 -04003784 if (length)
3785 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003786 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003787 }
3788
Jamie Madill0063c512014-08-25 15:47:53 -04003789 return true;
3790}
3791
He Yunchaoced53ae2016-11-29 15:00:51 +08003792bool ValidateGetnUniformfvEXT(Context *context,
3793 GLuint program,
3794 GLint location,
3795 GLsizei bufSize,
3796 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003797{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003798 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003799}
3800
He Yunchaoced53ae2016-11-29 15:00:51 +08003801bool ValidateGetnUniformivEXT(Context *context,
3802 GLuint program,
3803 GLint location,
3804 GLsizei bufSize,
3805 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003806{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003807 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3808}
3809
3810bool ValidateGetUniformfvRobustANGLE(Context *context,
3811 GLuint program,
3812 GLint location,
3813 GLsizei bufSize,
3814 GLsizei *length,
3815 GLfloat *params)
3816{
3817 if (!ValidateRobustEntryPoint(context, bufSize))
3818 {
3819 return false;
3820 }
3821
3822 // bufSize is validated in ValidateSizedGetUniform
3823 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3824}
3825
3826bool ValidateGetUniformivRobustANGLE(Context *context,
3827 GLuint program,
3828 GLint location,
3829 GLsizei bufSize,
3830 GLsizei *length,
3831 GLint *params)
3832{
3833 if (!ValidateRobustEntryPoint(context, bufSize))
3834 {
3835 return false;
3836 }
3837
3838 // bufSize is validated in ValidateSizedGetUniform
3839 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3840}
3841
3842bool ValidateGetUniformuivRobustANGLE(Context *context,
3843 GLuint program,
3844 GLint location,
3845 GLsizei bufSize,
3846 GLsizei *length,
3847 GLuint *params)
3848{
3849 if (!ValidateRobustEntryPoint(context, bufSize))
3850 {
3851 return false;
3852 }
3853
3854 if (context->getClientMajorVersion() < 3)
3855 {
3856 context->handleError(
3857 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3858 return false;
3859 }
3860
3861 // bufSize is validated in ValidateSizedGetUniform
3862 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003863}
3864
He Yunchaoced53ae2016-11-29 15:00:51 +08003865bool ValidateDiscardFramebufferBase(Context *context,
3866 GLenum target,
3867 GLsizei numAttachments,
3868 const GLenum *attachments,
3869 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003870{
3871 if (numAttachments < 0)
3872 {
Jamie Madill437fa652016-05-03 15:13:24 -04003873 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003874 return false;
3875 }
3876
3877 for (GLsizei i = 0; i < numAttachments; ++i)
3878 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003879 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003880 {
3881 if (defaultFramebuffer)
3882 {
Jamie Madill437fa652016-05-03 15:13:24 -04003883 context->handleError(Error(
3884 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003885 return false;
3886 }
3887
3888 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3889 {
Jamie Madill437fa652016-05-03 15:13:24 -04003890 context->handleError(Error(GL_INVALID_OPERATION,
3891 "Requested color attachment is greater than the maximum "
3892 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003893 return false;
3894 }
3895 }
3896 else
3897 {
3898 switch (attachments[i])
3899 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003900 case GL_DEPTH_ATTACHMENT:
3901 case GL_STENCIL_ATTACHMENT:
3902 case GL_DEPTH_STENCIL_ATTACHMENT:
3903 if (defaultFramebuffer)
3904 {
3905 context->handleError(
3906 Error(GL_INVALID_ENUM,
3907 "Invalid attachment when the default framebuffer is bound"));
3908 return false;
3909 }
3910 break;
3911 case GL_COLOR:
3912 case GL_DEPTH:
3913 case GL_STENCIL:
3914 if (!defaultFramebuffer)
3915 {
3916 context->handleError(
3917 Error(GL_INVALID_ENUM,
3918 "Invalid attachment when the default framebuffer is not bound"));
3919 return false;
3920 }
3921 break;
3922 default:
3923 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003924 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003925 }
3926 }
3927 }
3928
3929 return true;
3930}
3931
Austin Kinross6ee1e782015-05-29 17:05:37 -07003932bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3933{
3934 // Note that debug marker calls must not set error state
3935
3936 if (length < 0)
3937 {
3938 return false;
3939 }
3940
3941 if (marker == nullptr)
3942 {
3943 return false;
3944 }
3945
3946 return true;
3947}
3948
3949bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3950{
3951 // Note that debug marker calls must not set error state
3952
3953 if (length < 0)
3954 {
3955 return false;
3956 }
3957
3958 if (length > 0 && marker == nullptr)
3959 {
3960 return false;
3961 }
3962
3963 return true;
3964}
3965
Geoff Langdcab33b2015-07-21 13:03:16 -04003966bool ValidateEGLImageTargetTexture2DOES(Context *context,
3967 egl::Display *display,
3968 GLenum target,
3969 egl::Image *image)
3970{
Geoff Langa8406172015-07-21 16:53:39 -04003971 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3972 {
Jamie Madill437fa652016-05-03 15:13:24 -04003973 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003974 return false;
3975 }
3976
3977 switch (target)
3978 {
3979 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003980 if (!context->getExtensions().eglImage)
3981 {
3982 context->handleError(Error(
3983 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3984 }
3985 break;
3986
3987 case GL_TEXTURE_EXTERNAL_OES:
3988 if (!context->getExtensions().eglImageExternal)
3989 {
3990 context->handleError(Error(
3991 GL_INVALID_ENUM,
3992 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3993 }
Geoff Langa8406172015-07-21 16:53:39 -04003994 break;
3995
3996 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003997 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003998 return false;
3999 }
4000
4001 if (!display->isValidImage(image))
4002 {
Jamie Madill437fa652016-05-03 15:13:24 -04004003 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004004 return false;
4005 }
4006
4007 if (image->getSamples() > 0)
4008 {
Jamie Madill437fa652016-05-03 15:13:24 -04004009 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004010 "cannot create a 2D texture from a multisampled EGL image."));
4011 return false;
4012 }
4013
Jamie Madilla3944d42016-07-22 22:13:26 -04004014 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004015 if (!textureCaps.texturable)
4016 {
Jamie Madill437fa652016-05-03 15:13:24 -04004017 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04004018 "EGL image internal format is not supported as a texture."));
4019 return false;
4020 }
4021
Geoff Langdcab33b2015-07-21 13:03:16 -04004022 return true;
4023}
4024
4025bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
4026 egl::Display *display,
4027 GLenum target,
4028 egl::Image *image)
4029{
Geoff Langa8406172015-07-21 16:53:39 -04004030 if (!context->getExtensions().eglImage)
4031 {
Jamie Madill437fa652016-05-03 15:13:24 -04004032 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04004033 return false;
4034 }
4035
4036 switch (target)
4037 {
4038 case GL_RENDERBUFFER:
4039 break;
4040
4041 default:
Jamie Madill437fa652016-05-03 15:13:24 -04004042 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04004043 return false;
4044 }
4045
4046 if (!display->isValidImage(image))
4047 {
Jamie Madill437fa652016-05-03 15:13:24 -04004048 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04004049 return false;
4050 }
4051
Jamie Madilla3944d42016-07-22 22:13:26 -04004052 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004053 if (!textureCaps.renderable)
4054 {
Jamie Madill437fa652016-05-03 15:13:24 -04004055 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004056 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4057 return false;
4058 }
4059
Geoff Langdcab33b2015-07-21 13:03:16 -04004060 return true;
4061}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004062
4063bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4064{
Geoff Lang36167ab2015-12-07 10:27:14 -05004065 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004066 {
4067 // The default VAO should always exist
4068 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004069 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004070 return false;
4071 }
4072
4073 return true;
4074}
4075
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004076bool ValidateLinkProgram(Context *context, GLuint program)
4077{
4078 if (context->hasActiveTransformFeedback(program))
4079 {
4080 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004081 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004082 "Cannot link program while program is associated with an active "
4083 "transform feedback object."));
4084 return false;
4085 }
4086 return true;
4087}
4088
Geoff Langc5629752015-12-07 16:29:04 -05004089bool ValidateProgramBinaryBase(Context *context,
4090 GLuint program,
4091 GLenum binaryFormat,
4092 const void *binary,
4093 GLint length)
4094{
4095 Program *programObject = GetValidProgram(context, program);
4096 if (programObject == nullptr)
4097 {
4098 return false;
4099 }
4100
4101 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4102 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4103 programBinaryFormats.end())
4104 {
Jamie Madill437fa652016-05-03 15:13:24 -04004105 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004106 return false;
4107 }
4108
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004109 if (context->hasActiveTransformFeedback(program))
4110 {
4111 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004112 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004113 "Cannot change program binary while program is associated with "
4114 "an active transform feedback object."));
4115 return false;
4116 }
4117
Geoff Langc5629752015-12-07 16:29:04 -05004118 return true;
4119}
4120
4121bool ValidateGetProgramBinaryBase(Context *context,
4122 GLuint program,
4123 GLsizei bufSize,
4124 GLsizei *length,
4125 GLenum *binaryFormat,
4126 void *binary)
4127{
4128 Program *programObject = GetValidProgram(context, program);
4129 if (programObject == nullptr)
4130 {
4131 return false;
4132 }
4133
4134 if (!programObject->isLinked())
4135 {
Jamie Madill437fa652016-05-03 15:13:24 -04004136 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004137 return false;
4138 }
4139
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004140 if (context->getCaps().programBinaryFormats.empty())
4141 {
4142 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4143 return false;
4144 }
4145
Geoff Langc5629752015-12-07 16:29:04 -05004146 return true;
4147}
Jamie Madillc29968b2016-01-20 11:17:23 -05004148
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004149bool ValidateUseProgram(Context *context, GLuint program)
4150{
4151 if (program != 0)
4152 {
4153 Program *programObject = context->getProgram(program);
4154 if (!programObject)
4155 {
4156 // ES 3.1.0 section 7.3 page 72
4157 if (context->getShader(program))
4158 {
Jamie Madill437fa652016-05-03 15:13:24 -04004159 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004160 Error(GL_INVALID_OPERATION,
4161 "Attempted to use a single shader instead of a shader program."));
4162 return false;
4163 }
4164 else
4165 {
Jamie Madill437fa652016-05-03 15:13:24 -04004166 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004167 return false;
4168 }
4169 }
4170 if (!programObject->isLinked())
4171 {
Jamie Madill437fa652016-05-03 15:13:24 -04004172 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004173 return false;
4174 }
4175 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004176 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004177 {
4178 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004179 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004180 Error(GL_INVALID_OPERATION,
4181 "Cannot change active program while transform feedback is unpaused."));
4182 return false;
4183 }
4184
4185 return true;
4186}
4187
Jamie Madillc29968b2016-01-20 11:17:23 -05004188bool ValidateCopyTexImage2D(ValidationContext *context,
4189 GLenum target,
4190 GLint level,
4191 GLenum internalformat,
4192 GLint x,
4193 GLint y,
4194 GLsizei width,
4195 GLsizei height,
4196 GLint border)
4197{
Martin Radev1be913c2016-07-11 17:59:16 +03004198 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004199 {
4200 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4201 0, x, y, width, height, border);
4202 }
4203
Martin Radev1be913c2016-07-11 17:59:16 +03004204 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004205 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4206 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004207}
Jamie Madillc29968b2016-01-20 11:17:23 -05004208
4209bool ValidateFramebufferRenderbuffer(Context *context,
4210 GLenum target,
4211 GLenum attachment,
4212 GLenum renderbuffertarget,
4213 GLuint renderbuffer)
4214{
4215 if (!ValidFramebufferTarget(target) ||
4216 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4217 {
Jamie Madill437fa652016-05-03 15:13:24 -04004218 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004219 return false;
4220 }
4221
4222 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4223 renderbuffertarget, renderbuffer);
4224}
4225
4226bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4227{
4228 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4229 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4230 {
Jamie Madill437fa652016-05-03 15:13:24 -04004231 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004232 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4233 return false;
4234 }
4235
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004236 ASSERT(context->getGLState().getDrawFramebuffer());
4237 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004238 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4239
4240 // This should come first before the check for the default frame buffer
4241 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4242 // rather than INVALID_OPERATION
4243 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4244 {
4245 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4246
4247 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004248 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4249 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004250 {
4251 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004252 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4253 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4254 // 3.1 is still a bit ambiguous about the error, but future specs are
4255 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004256 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004257 return false;
4258 }
4259 else if (bufs[colorAttachment] >= maxColorAttachment)
4260 {
Jamie Madill437fa652016-05-03 15:13:24 -04004261 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004262 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004263 return false;
4264 }
4265 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4266 frameBufferId != 0)
4267 {
4268 // INVALID_OPERATION-GL is bound to buffer and ith argument
4269 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004270 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004271 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4272 return false;
4273 }
4274 }
4275
4276 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4277 // and n is not 1 or bufs is bound to value other than BACK and NONE
4278 if (frameBufferId == 0)
4279 {
4280 if (n != 1)
4281 {
Jamie Madill437fa652016-05-03 15:13:24 -04004282 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004283 "n must be 1 when GL is bound to the default framebuffer"));
4284 return false;
4285 }
4286
4287 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4288 {
Jamie Madill437fa652016-05-03 15:13:24 -04004289 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004290 GL_INVALID_OPERATION,
4291 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4292 return false;
4293 }
4294 }
4295
4296 return true;
4297}
4298
4299bool ValidateCopyTexSubImage2D(Context *context,
4300 GLenum target,
4301 GLint level,
4302 GLint xoffset,
4303 GLint yoffset,
4304 GLint x,
4305 GLint y,
4306 GLsizei width,
4307 GLsizei height)
4308{
Martin Radev1be913c2016-07-11 17:59:16 +03004309 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004310 {
4311 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4312 yoffset, x, y, width, height, 0);
4313 }
4314
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004315 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4316 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004317}
4318
Geoff Lang496c02d2016-10-20 11:38:11 -07004319bool ValidateGetBufferPointervBase(Context *context,
4320 GLenum target,
4321 GLenum pname,
4322 GLsizei *length,
4323 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004324{
Geoff Lang496c02d2016-10-20 11:38:11 -07004325 if (length)
4326 {
4327 *length = 0;
4328 }
4329
4330 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4331 {
4332 context->handleError(
4333 Error(GL_INVALID_OPERATION,
4334 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
4335 return false;
4336 }
4337
Olli Etuaho4f667482016-03-30 15:56:35 +03004338 if (!ValidBufferTarget(context, target))
4339 {
Jamie Madill437fa652016-05-03 15:13:24 -04004340 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004341 return false;
4342 }
4343
Geoff Lang496c02d2016-10-20 11:38:11 -07004344 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004345 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004346 case GL_BUFFER_MAP_POINTER:
4347 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004348
Geoff Lang496c02d2016-10-20 11:38:11 -07004349 default:
4350 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4351 return false;
4352 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004353
4354 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4355 // target bound to zero generate an INVALID_OPERATION error."
4356 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004357 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004358 {
Jamie Madill437fa652016-05-03 15:13:24 -04004359 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004360 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4361 return false;
4362 }
4363
Geoff Lang496c02d2016-10-20 11:38:11 -07004364 if (length)
4365 {
4366 *length = 1;
4367 }
4368
Olli Etuaho4f667482016-03-30 15:56:35 +03004369 return true;
4370}
4371
4372bool ValidateUnmapBufferBase(Context *context, GLenum target)
4373{
4374 if (!ValidBufferTarget(context, target))
4375 {
Jamie Madill437fa652016-05-03 15:13:24 -04004376 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004377 return false;
4378 }
4379
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004380 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004381
4382 if (buffer == nullptr || !buffer->isMapped())
4383 {
Jamie Madill437fa652016-05-03 15:13:24 -04004384 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004385 return false;
4386 }
4387
4388 return true;
4389}
4390
4391bool ValidateMapBufferRangeBase(Context *context,
4392 GLenum target,
4393 GLintptr offset,
4394 GLsizeiptr length,
4395 GLbitfield access)
4396{
4397 if (!ValidBufferTarget(context, target))
4398 {
Jamie Madill437fa652016-05-03 15:13:24 -04004399 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004400 return false;
4401 }
4402
4403 if (offset < 0 || length < 0)
4404 {
Jamie Madill437fa652016-05-03 15:13:24 -04004405 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004406 return false;
4407 }
4408
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004409 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004410
4411 if (!buffer)
4412 {
Jamie Madill437fa652016-05-03 15:13:24 -04004413 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004414 return false;
4415 }
4416
4417 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004418 CheckedNumeric<size_t> checkedOffset(offset);
4419 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004420
Jamie Madille2e406c2016-06-02 13:04:10 -04004421 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004422 {
Jamie Madill437fa652016-05-03 15:13:24 -04004423 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004424 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4425 return false;
4426 }
4427
4428 // Check for invalid bits in the mask
4429 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4430 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4431 GL_MAP_UNSYNCHRONIZED_BIT;
4432
4433 if (access & ~(allAccessBits))
4434 {
Jamie Madill437fa652016-05-03 15:13:24 -04004435 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004436 return false;
4437 }
4438
4439 if (length == 0)
4440 {
Jamie Madill437fa652016-05-03 15:13:24 -04004441 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004442 return false;
4443 }
4444
4445 if (buffer->isMapped())
4446 {
Jamie Madill437fa652016-05-03 15:13:24 -04004447 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004448 return false;
4449 }
4450
4451 // Check for invalid bit combinations
4452 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4453 {
Jamie Madill437fa652016-05-03 15:13:24 -04004454 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004455 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4456 return false;
4457 }
4458
4459 GLbitfield writeOnlyBits =
4460 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4461
4462 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4463 {
Jamie Madill437fa652016-05-03 15:13:24 -04004464 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004465 "Invalid access bits when mapping buffer for reading: 0x%X.",
4466 access));
4467 return false;
4468 }
4469
4470 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4471 {
Jamie Madill437fa652016-05-03 15:13:24 -04004472 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004473 GL_INVALID_OPERATION,
4474 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4475 return false;
4476 }
4477 return true;
4478}
4479
4480bool ValidateFlushMappedBufferRangeBase(Context *context,
4481 GLenum target,
4482 GLintptr offset,
4483 GLsizeiptr length)
4484{
4485 if (offset < 0 || length < 0)
4486 {
Jamie Madill437fa652016-05-03 15:13:24 -04004487 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004488 return false;
4489 }
4490
4491 if (!ValidBufferTarget(context, target))
4492 {
Jamie Madill437fa652016-05-03 15:13:24 -04004493 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004494 return false;
4495 }
4496
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004497 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004498
4499 if (buffer == nullptr)
4500 {
Jamie Madill437fa652016-05-03 15:13:24 -04004501 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004502 return false;
4503 }
4504
4505 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4506 {
Jamie Madill437fa652016-05-03 15:13:24 -04004507 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004508 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4509 return false;
4510 }
4511
4512 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004513 CheckedNumeric<size_t> checkedOffset(offset);
4514 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004515
Jamie Madille2e406c2016-06-02 13:04:10 -04004516 if (!checkedSize.IsValid() ||
4517 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004518 {
Jamie Madill437fa652016-05-03 15:13:24 -04004519 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004520 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4521 return false;
4522 }
4523
4524 return true;
4525}
4526
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004527bool ValidateGenerateMipmap(Context *context, GLenum target)
4528{
4529 if (!ValidTextureTarget(context, target))
4530 {
4531 context->handleError(Error(GL_INVALID_ENUM));
4532 return false;
4533 }
4534
4535 Texture *texture = context->getTargetTexture(target);
4536
4537 if (texture == nullptr)
4538 {
4539 context->handleError(Error(GL_INVALID_OPERATION));
4540 return false;
4541 }
4542
4543 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4544
4545 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4546 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4547 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4548 {
4549 context->handleError(Error(GL_INVALID_OPERATION));
4550 return false;
4551 }
4552
Jamie Madilla3944d42016-07-22 22:13:26 -04004553 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4554 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4555 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004556
4557 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4558 // unsized formats or that are color renderable and filterable. Since we do not track if
4559 // the texture was created with sized or unsized format (only sized formats are stored),
4560 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4561 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4562 // textures since they're the only texture format that can be created with unsized formats
4563 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4564 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004565 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4566 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004567 {
4568 context->handleError(Error(GL_INVALID_OPERATION));
4569 return false;
4570 }
4571
4572 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004573 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004574 {
4575 context->handleError(Error(GL_INVALID_OPERATION));
4576 return false;
4577 }
4578
4579 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004580 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004581 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4582 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4583 {
Geoff Lang55482a12016-11-21 16:54:01 -05004584 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004585 context->handleError(Error(GL_INVALID_OPERATION));
4586 return false;
4587 }
4588
4589 // Cube completeness check
4590 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4591 {
4592 context->handleError(Error(GL_INVALID_OPERATION));
4593 return false;
4594 }
4595
4596 return true;
4597}
4598
Olli Etuaho41997e72016-03-10 13:38:39 +02004599bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4600{
4601 return ValidateGenOrDelete(context, n);
4602}
4603
4604bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4605{
4606 return ValidateGenOrDelete(context, n);
4607}
4608
4609bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4610{
4611 return ValidateGenOrDelete(context, n);
4612}
4613
4614bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4615{
4616 return ValidateGenOrDelete(context, n);
4617}
4618
4619bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4620{
4621 return ValidateGenOrDelete(context, n);
4622}
4623
4624bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4625{
4626 return ValidateGenOrDelete(context, n);
4627}
4628
4629bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4630{
4631 return ValidateGenOrDelete(context, n);
4632}
4633
4634bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4635{
4636 return ValidateGenOrDelete(context, n);
4637}
4638
4639bool ValidateGenOrDelete(Context *context, GLint n)
4640{
4641 if (n < 0)
4642 {
Jamie Madill437fa652016-05-03 15:13:24 -04004643 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004644 return false;
4645 }
4646 return true;
4647}
4648
Geoff Langf41a7152016-09-19 15:11:17 -04004649bool ValidateEnable(Context *context, GLenum cap)
4650{
4651 if (!ValidCap(context, cap, false))
4652 {
4653 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4654 return false;
4655 }
4656
4657 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4658 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4659 {
4660 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4661 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4662
4663 // We also output an error message to the debugger window if tracing is active, so that
4664 // developers can see the error message.
Jamie Madill6a6b09c2017-01-12 21:52:29 +00004665 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004666 return false;
4667 }
4668
4669 return true;
4670}
4671
4672bool ValidateDisable(Context *context, GLenum cap)
4673{
4674 if (!ValidCap(context, cap, false))
4675 {
4676 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4677 return false;
4678 }
4679
4680 return true;
4681}
4682
4683bool ValidateIsEnabled(Context *context, GLenum cap)
4684{
4685 if (!ValidCap(context, cap, true))
4686 {
4687 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4688 return false;
4689 }
4690
4691 return true;
4692}
4693
Geoff Langff5b2d52016-09-07 11:32:23 -04004694bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4695{
4696 if (!context->getExtensions().robustClientMemory)
4697 {
4698 context->handleError(
4699 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4700 return false;
4701 }
4702
4703 if (bufSize < 0)
4704 {
4705 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4706 return false;
4707 }
4708
4709 return true;
4710}
4711
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004712bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4713{
4714 if (bufSize < numParams)
4715 {
4716 context->handleError(Error(GL_INVALID_OPERATION,
4717 "%u parameters are required but %i were provided.", numParams,
4718 bufSize));
4719 return false;
4720 }
4721
4722 return true;
4723}
4724
Geoff Langff5b2d52016-09-07 11:32:23 -04004725bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4726 GLenum target,
4727 GLenum attachment,
4728 GLenum pname,
4729 GLsizei *numParams)
4730{
4731 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4732 *numParams = 1;
4733
4734 if (!ValidFramebufferTarget(target))
4735 {
4736 context->handleError(Error(GL_INVALID_ENUM));
4737 return false;
4738 }
4739
4740 int clientVersion = context->getClientMajorVersion();
4741
4742 switch (pname)
4743 {
4744 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4745 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4746 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4747 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4748 break;
4749
4750 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4751 if (clientVersion < 3 && !context->getExtensions().sRGB)
4752 {
4753 context->handleError(Error(GL_INVALID_ENUM));
4754 return false;
4755 }
4756 break;
4757
4758 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4759 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4760 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4761 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4762 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4763 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4764 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4765 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4766 if (clientVersion < 3)
4767 {
4768 context->handleError(Error(GL_INVALID_ENUM));
4769 return false;
4770 }
4771 break;
4772
4773 default:
4774 context->handleError(Error(GL_INVALID_ENUM));
4775 return false;
4776 }
4777
4778 // Determine if the attachment is a valid enum
4779 switch (attachment)
4780 {
4781 case GL_BACK:
4782 case GL_FRONT:
4783 case GL_DEPTH:
4784 case GL_STENCIL:
4785 case GL_DEPTH_STENCIL_ATTACHMENT:
4786 if (clientVersion < 3)
4787 {
4788 context->handleError(Error(GL_INVALID_ENUM));
4789 return false;
4790 }
4791 break;
4792
4793 case GL_DEPTH_ATTACHMENT:
4794 case GL_STENCIL_ATTACHMENT:
4795 break;
4796
4797 default:
4798 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4799 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4800 {
4801 context->handleError(Error(GL_INVALID_ENUM));
4802 return false;
4803 }
4804 break;
4805 }
4806
4807 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4808 ASSERT(framebuffer);
4809
4810 if (framebuffer->id() == 0)
4811 {
4812 if (clientVersion < 3)
4813 {
4814 context->handleError(Error(GL_INVALID_OPERATION));
4815 return false;
4816 }
4817
4818 switch (attachment)
4819 {
4820 case GL_BACK:
4821 case GL_DEPTH:
4822 case GL_STENCIL:
4823 break;
4824
4825 default:
4826 context->handleError(Error(GL_INVALID_OPERATION));
4827 return false;
4828 }
4829 }
4830 else
4831 {
4832 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4833 {
4834 // Valid attachment query
4835 }
4836 else
4837 {
4838 switch (attachment)
4839 {
4840 case GL_DEPTH_ATTACHMENT:
4841 case GL_STENCIL_ATTACHMENT:
4842 break;
4843
4844 case GL_DEPTH_STENCIL_ATTACHMENT:
4845 if (!framebuffer->hasValidDepthStencil())
4846 {
4847 context->handleError(Error(GL_INVALID_OPERATION));
4848 return false;
4849 }
4850 break;
4851
4852 default:
4853 context->handleError(Error(GL_INVALID_OPERATION));
4854 return false;
4855 }
4856 }
4857 }
4858
4859 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4860 if (attachmentObject)
4861 {
4862 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4863 attachmentObject->type() == GL_TEXTURE ||
4864 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4865
4866 switch (pname)
4867 {
4868 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4869 if (attachmentObject->type() != GL_RENDERBUFFER &&
4870 attachmentObject->type() != GL_TEXTURE)
4871 {
4872 context->handleError(Error(GL_INVALID_ENUM));
4873 return false;
4874 }
4875 break;
4876
4877 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4878 if (attachmentObject->type() != GL_TEXTURE)
4879 {
4880 context->handleError(Error(GL_INVALID_ENUM));
4881 return false;
4882 }
4883 break;
4884
4885 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4886 if (attachmentObject->type() != GL_TEXTURE)
4887 {
4888 context->handleError(Error(GL_INVALID_ENUM));
4889 return false;
4890 }
4891 break;
4892
4893 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4894 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4895 {
4896 context->handleError(Error(GL_INVALID_OPERATION));
4897 return false;
4898 }
4899 break;
4900
4901 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4902 if (attachmentObject->type() != GL_TEXTURE)
4903 {
4904 context->handleError(Error(GL_INVALID_ENUM));
4905 return false;
4906 }
4907 break;
4908
4909 default:
4910 break;
4911 }
4912 }
4913 else
4914 {
4915 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4916 // is NONE, then querying any other pname will generate INVALID_ENUM.
4917
4918 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4919 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4920 // INVALID_OPERATION for all other pnames
4921
4922 switch (pname)
4923 {
4924 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4925 break;
4926
4927 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4928 if (clientVersion < 3)
4929 {
4930 context->handleError(Error(GL_INVALID_ENUM));
4931 return false;
4932 }
4933 break;
4934
4935 default:
4936 if (clientVersion < 3)
4937 {
4938 context->handleError(Error(GL_INVALID_ENUM));
4939 return false;
4940 }
4941 else
4942 {
4943 context->handleError(Error(GL_INVALID_OPERATION));
4944 return false;
4945 }
4946 }
4947 }
4948
4949 return true;
4950}
4951
4952bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4953 GLenum target,
4954 GLenum attachment,
4955 GLenum pname,
4956 GLsizei bufSize,
4957 GLsizei *numParams)
4958{
4959 if (!ValidateRobustEntryPoint(context, bufSize))
4960 {
4961 return false;
4962 }
4963
4964 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4965 {
4966 return false;
4967 }
4968
4969 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4970 {
4971 return false;
4972 }
4973
4974 return true;
4975}
4976
4977bool ValidateGetBufferParameteriv(ValidationContext *context,
4978 GLenum target,
4979 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004980 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004981{
Geoff Langebebe1c2016-10-14 12:01:31 -04004982 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004983}
4984
4985bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4986 GLenum target,
4987 GLenum pname,
4988 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004989 GLsizei *length,
4990 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004991{
4992 if (!ValidateRobustEntryPoint(context, bufSize))
4993 {
4994 return false;
4995 }
4996
Geoff Langebebe1c2016-10-14 12:01:31 -04004997 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004998 {
4999 return false;
5000 }
5001
Geoff Langebebe1c2016-10-14 12:01:31 -04005002 if (!ValidateRobustBufferSize(context, bufSize, *length))
5003 {
5004 return false;
5005 }
5006
5007 return true;
5008}
5009
5010bool ValidateGetBufferParameteri64v(ValidationContext *context,
5011 GLenum target,
5012 GLenum pname,
5013 GLint64 *params)
5014{
5015 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
5016}
5017
5018bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
5019 GLenum target,
5020 GLenum pname,
5021 GLsizei bufSize,
5022 GLsizei *length,
5023 GLint64 *params)
5024{
5025 if (!ValidateRobustEntryPoint(context, bufSize))
5026 {
5027 return false;
5028 }
5029
5030 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
5031 {
5032 return false;
5033 }
5034
5035 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04005036 {
5037 return false;
5038 }
5039
5040 return true;
5041}
5042
5043bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
5044{
5045 // Currently, all GetProgramiv queries return 1 parameter
5046 *numParams = 1;
5047
5048 Program *programObject = GetValidProgram(context, program);
5049 if (!programObject)
5050 {
5051 return false;
5052 }
5053
5054 switch (pname)
5055 {
5056 case GL_DELETE_STATUS:
5057 case GL_LINK_STATUS:
5058 case GL_VALIDATE_STATUS:
5059 case GL_INFO_LOG_LENGTH:
5060 case GL_ATTACHED_SHADERS:
5061 case GL_ACTIVE_ATTRIBUTES:
5062 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5063 case GL_ACTIVE_UNIFORMS:
5064 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5065 break;
5066
5067 case GL_PROGRAM_BINARY_LENGTH:
5068 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5069 {
5070 context->handleError(Error(GL_INVALID_ENUM,
5071 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5072 "GL_OES_get_program_binary or ES 3.0."));
5073 return false;
5074 }
5075 break;
5076
5077 case GL_ACTIVE_UNIFORM_BLOCKS:
5078 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5079 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5080 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5081 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5082 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5083 if (context->getClientMajorVersion() < 3)
5084 {
5085 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5086 return false;
5087 }
5088 break;
5089
5090 default:
5091 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5092 return false;
5093 }
5094
5095 return true;
5096}
5097
5098bool ValidateGetProgramivRobustANGLE(Context *context,
5099 GLuint program,
5100 GLenum pname,
5101 GLsizei bufSize,
5102 GLsizei *numParams)
5103{
5104 if (!ValidateRobustEntryPoint(context, bufSize))
5105 {
5106 return false;
5107 }
5108
5109 if (!ValidateGetProgramiv(context, program, pname, numParams))
5110 {
5111 return false;
5112 }
5113
5114 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5115 {
5116 return false;
5117 }
5118
5119 return true;
5120}
5121
Geoff Lang740d9022016-10-07 11:20:52 -04005122bool ValidateGetRenderbufferParameteriv(Context *context,
5123 GLenum target,
5124 GLenum pname,
5125 GLint *params)
5126{
5127 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5128}
5129
5130bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5131 GLenum target,
5132 GLenum pname,
5133 GLsizei bufSize,
5134 GLsizei *length,
5135 GLint *params)
5136{
5137 if (!ValidateRobustEntryPoint(context, bufSize))
5138 {
5139 return false;
5140 }
5141
5142 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5143 {
5144 return false;
5145 }
5146
5147 if (!ValidateRobustBufferSize(context, bufSize, *length))
5148 {
5149 return false;
5150 }
5151
5152 return true;
5153}
5154
Geoff Langd7d0ed32016-10-07 11:33:51 -04005155bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5156{
5157 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5158}
5159
5160bool ValidateGetShaderivRobustANGLE(Context *context,
5161 GLuint shader,
5162 GLenum pname,
5163 GLsizei bufSize,
5164 GLsizei *length,
5165 GLint *params)
5166{
5167 if (!ValidateRobustEntryPoint(context, bufSize))
5168 {
5169 return false;
5170 }
5171
5172 if (!ValidateGetShaderivBase(context, shader, pname, length))
5173 {
5174 return false;
5175 }
5176
5177 if (!ValidateRobustBufferSize(context, bufSize, *length))
5178 {
5179 return false;
5180 }
5181
5182 return true;
5183}
5184
Geoff Langc1984ed2016-10-07 12:41:00 -04005185bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5186{
5187 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5188}
5189
5190bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5191 GLenum target,
5192 GLenum pname,
5193 GLsizei bufSize,
5194 GLsizei *length,
5195 GLfloat *params)
5196{
5197 if (!ValidateRobustEntryPoint(context, bufSize))
5198 {
5199 return false;
5200 }
5201
5202 if (!ValidateGetTexParameterBase(context, target, pname, length))
5203 {
5204 return false;
5205 }
5206
5207 if (!ValidateRobustBufferSize(context, bufSize, *length))
5208 {
5209 return false;
5210 }
5211
5212 return true;
5213}
5214
5215bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5216{
5217 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5218}
5219
5220bool ValidateGetTexParameterivRobustANGLE(Context *context,
5221 GLenum target,
5222 GLenum pname,
5223 GLsizei bufSize,
5224 GLsizei *length,
5225 GLint *params)
5226{
5227 if (!ValidateRobustEntryPoint(context, bufSize))
5228 {
5229 return false;
5230 }
5231
5232 if (!ValidateGetTexParameterBase(context, target, pname, length))
5233 {
5234 return false;
5235 }
5236
5237 if (!ValidateRobustBufferSize(context, bufSize, *length))
5238 {
5239 return false;
5240 }
5241
5242 return true;
5243}
5244
5245bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5246{
5247 return ValidateTexParameterBase(context, target, pname, -1, &param);
5248}
5249
5250bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5251{
5252 return ValidateTexParameterBase(context, target, pname, -1, params);
5253}
5254
5255bool ValidateTexParameterfvRobustANGLE(Context *context,
5256 GLenum target,
5257 GLenum pname,
5258 GLsizei bufSize,
5259 const GLfloat *params)
5260{
5261 if (!ValidateRobustEntryPoint(context, bufSize))
5262 {
5263 return false;
5264 }
5265
5266 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5267}
5268
5269bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5270{
5271 return ValidateTexParameterBase(context, target, pname, -1, &param);
5272}
5273
5274bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5275{
5276 return ValidateTexParameterBase(context, target, pname, -1, params);
5277}
5278
5279bool ValidateTexParameterivRobustANGLE(Context *context,
5280 GLenum target,
5281 GLenum pname,
5282 GLsizei bufSize,
5283 const GLint *params)
5284{
5285 if (!ValidateRobustEntryPoint(context, bufSize))
5286 {
5287 return false;
5288 }
5289
5290 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5291}
5292
5293bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5294{
5295 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5296}
5297
5298bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5299 GLuint sampler,
5300 GLenum pname,
5301 GLuint bufSize,
5302 GLsizei *length,
5303 GLfloat *params)
5304{
5305 if (!ValidateRobustEntryPoint(context, bufSize))
5306 {
5307 return false;
5308 }
5309
5310 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5311 {
5312 return false;
5313 }
5314
5315 if (!ValidateRobustBufferSize(context, bufSize, *length))
5316 {
5317 return false;
5318 }
5319
5320 return true;
5321}
5322
5323bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5324{
5325 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5326}
5327
5328bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5329 GLuint sampler,
5330 GLenum pname,
5331 GLuint bufSize,
5332 GLsizei *length,
5333 GLint *params)
5334{
5335 if (!ValidateRobustEntryPoint(context, bufSize))
5336 {
5337 return false;
5338 }
5339
5340 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5341 {
5342 return false;
5343 }
5344
5345 if (!ValidateRobustBufferSize(context, bufSize, *length))
5346 {
5347 return false;
5348 }
5349
5350 return true;
5351}
5352
5353bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5354{
5355 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5356}
5357
5358bool ValidateSamplerParameterfv(Context *context,
5359 GLuint sampler,
5360 GLenum pname,
5361 const GLfloat *params)
5362{
5363 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5364}
5365
5366bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5367 GLuint sampler,
5368 GLenum pname,
5369 GLsizei bufSize,
5370 const GLfloat *params)
5371{
5372 if (!ValidateRobustEntryPoint(context, bufSize))
5373 {
5374 return false;
5375 }
5376
5377 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5378}
5379
5380bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5381{
5382 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5383}
5384
5385bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5386{
5387 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5388}
5389
5390bool ValidateSamplerParameterivRobustANGLE(Context *context,
5391 GLuint sampler,
5392 GLenum pname,
5393 GLsizei bufSize,
5394 const GLint *params)
5395{
5396 if (!ValidateRobustEntryPoint(context, bufSize))
5397 {
5398 return false;
5399 }
5400
5401 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5402}
5403
Geoff Lang0b031062016-10-13 14:30:04 -04005404bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5405{
5406 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5407}
5408
5409bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5410 GLuint index,
5411 GLenum pname,
5412 GLsizei bufSize,
5413 GLsizei *length,
5414 GLfloat *params)
5415{
5416 if (!ValidateRobustEntryPoint(context, bufSize))
5417 {
5418 return false;
5419 }
5420
5421 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5422 {
5423 return false;
5424 }
5425
5426 if (!ValidateRobustBufferSize(context, bufSize, *length))
5427 {
5428 return false;
5429 }
5430
5431 return true;
5432}
5433
5434bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5435{
5436 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5437}
5438
5439bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5440 GLuint index,
5441 GLenum pname,
5442 GLsizei bufSize,
5443 GLsizei *length,
5444 GLint *params)
5445{
5446 if (!ValidateRobustEntryPoint(context, bufSize))
5447 {
5448 return false;
5449 }
5450
5451 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5452 {
5453 return false;
5454 }
5455
5456 if (!ValidateRobustBufferSize(context, bufSize, *length))
5457 {
5458 return false;
5459 }
5460
5461 return true;
5462}
5463
5464bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5465{
5466 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5467}
5468
5469bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5470 GLuint index,
5471 GLenum pname,
5472 GLsizei bufSize,
5473 GLsizei *length,
5474 void **pointer)
5475{
5476 if (!ValidateRobustEntryPoint(context, bufSize))
5477 {
5478 return false;
5479 }
5480
5481 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5482 {
5483 return false;
5484 }
5485
5486 if (!ValidateRobustBufferSize(context, bufSize, *length))
5487 {
5488 return false;
5489 }
5490
5491 return true;
5492}
5493
5494bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5495{
5496 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5497}
5498
5499bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5500 GLuint index,
5501 GLenum pname,
5502 GLsizei bufSize,
5503 GLsizei *length,
5504 GLint *params)
5505{
5506 if (!ValidateRobustEntryPoint(context, bufSize))
5507 {
5508 return false;
5509 }
5510
5511 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5512 {
5513 return false;
5514 }
5515
5516 if (!ValidateRobustBufferSize(context, bufSize, *length))
5517 {
5518 return false;
5519 }
5520
5521 return true;
5522}
5523
5524bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5525{
5526 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5527}
5528
5529bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5530 GLuint index,
5531 GLenum pname,
5532 GLsizei bufSize,
5533 GLsizei *length,
5534 GLuint *params)
5535{
5536 if (!ValidateRobustEntryPoint(context, bufSize))
5537 {
5538 return false;
5539 }
5540
5541 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5542 {
5543 return false;
5544 }
5545
5546 if (!ValidateRobustBufferSize(context, bufSize, *length))
5547 {
5548 return false;
5549 }
5550
5551 return true;
5552}
5553
Geoff Lang6899b872016-10-14 11:30:13 -04005554bool ValidateGetActiveUniformBlockiv(Context *context,
5555 GLuint program,
5556 GLuint uniformBlockIndex,
5557 GLenum pname,
5558 GLint *params)
5559{
5560 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5561}
5562
5563bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5564 GLuint program,
5565 GLuint uniformBlockIndex,
5566 GLenum pname,
5567 GLsizei bufSize,
5568 GLsizei *length,
5569 GLint *params)
5570{
5571 if (!ValidateRobustEntryPoint(context, bufSize))
5572 {
5573 return false;
5574 }
5575
5576 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5577 {
5578 return false;
5579 }
5580
5581 if (!ValidateRobustBufferSize(context, bufSize, *length))
5582 {
5583 return false;
5584 }
5585
5586 return true;
5587}
5588
Geoff Lang0a9661f2016-10-20 10:59:20 -07005589bool ValidateGetInternalFormativ(Context *context,
5590 GLenum target,
5591 GLenum internalformat,
5592 GLenum pname,
5593 GLsizei bufSize,
5594 GLint *params)
5595{
5596 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5597 nullptr);
5598}
5599
5600bool ValidateGetInternalFormativRobustANGLE(Context *context,
5601 GLenum target,
5602 GLenum internalformat,
5603 GLenum pname,
5604 GLsizei bufSize,
5605 GLsizei *length,
5606 GLint *params)
5607{
5608 if (!ValidateRobustEntryPoint(context, bufSize))
5609 {
5610 return false;
5611 }
5612
5613 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5614 {
5615 return false;
5616 }
5617
5618 if (!ValidateRobustBufferSize(context, bufSize, *length))
5619 {
5620 return false;
5621 }
5622
5623 return true;
5624}
5625
Jamie Madillc29968b2016-01-20 11:17:23 -05005626} // namespace gl