blob: f07b2169139343222efe82b4f09d210f2b347ae2 [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
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001442bool ValidFramebufferTarget(GLenum target)
1443{
He Yunchaoced53ae2016-11-29 15:00:51 +08001444 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1445 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001446 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001447
1448 switch (target)
1449 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001450 case GL_FRAMEBUFFER:
1451 return true;
1452 case GL_READ_FRAMEBUFFER:
1453 return true;
1454 case GL_DRAW_FRAMEBUFFER:
1455 return true;
1456 default:
1457 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001458 }
1459}
1460
Jamie Madill29639852016-09-02 15:00:09 -04001461bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001462{
1463 switch (target)
1464 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001465 case GL_ARRAY_BUFFER:
1466 case GL_ELEMENT_ARRAY_BUFFER:
1467 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001468
He Yunchaoced53ae2016-11-29 15:00:51 +08001469 case GL_PIXEL_PACK_BUFFER:
1470 case GL_PIXEL_UNPACK_BUFFER:
1471 return (context->getExtensions().pixelBufferObject ||
1472 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001473
He Yunchaoced53ae2016-11-29 15:00:51 +08001474 case GL_COPY_READ_BUFFER:
1475 case GL_COPY_WRITE_BUFFER:
1476 case GL_TRANSFORM_FEEDBACK_BUFFER:
1477 case GL_UNIFORM_BUFFER:
1478 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001479
He Yunchaoced53ae2016-11-29 15:00:51 +08001480 case GL_ATOMIC_COUNTER_BUFFER:
1481 case GL_SHADER_STORAGE_BUFFER:
1482 case GL_DRAW_INDIRECT_BUFFER:
1483 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001484 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001485
He Yunchaoced53ae2016-11-29 15:00:51 +08001486 default:
1487 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001488 }
1489}
1490
Jamie Madillc29968b2016-01-20 11:17:23 -05001491bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001492{
Jamie Madillc29968b2016-01-20 11:17:23 -05001493 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001494 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001495 switch (target)
1496 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001497 case GL_TEXTURE_2D:
1498 maxDimension = caps.max2DTextureSize;
1499 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001500 case GL_TEXTURE_CUBE_MAP:
1501 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1502 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1503 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1504 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1505 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1506 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1507 maxDimension = caps.maxCubeMapTextureSize;
1508 break;
1509 case GL_TEXTURE_3D:
1510 maxDimension = caps.max3DTextureSize;
1511 break;
1512 case GL_TEXTURE_2D_ARRAY:
1513 maxDimension = caps.max2DTextureSize;
1514 break;
1515 default:
1516 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001517 }
1518
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001519 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001520}
1521
Geoff Langcc507aa2016-12-12 10:09:52 -05001522bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001523 GLenum target,
1524 GLint level,
1525 GLsizei width,
1526 GLsizei height,
1527 GLsizei depth,
1528 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001529{
1530 if (level < 0 || width < 0 || height < 0 || depth < 0)
1531 {
1532 return false;
1533 }
1534
Austin Kinross08528e12015-10-07 16:24:40 -07001535 // TexSubImage parameters can be NPOT without textureNPOT extension,
1536 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001537 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001538 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001539 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001540 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001541 {
1542 return false;
1543 }
1544
1545 if (!ValidMipLevel(context, target, level))
1546 {
1547 return false;
1548 }
1549
1550 return true;
1551}
1552
Geoff Lang0d8b7242015-09-09 14:56:53 -04001553bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1554{
1555 // List of compressed format that require that the texture size is smaller than or a multiple of
1556 // the compressed block size.
1557 switch (internalFormat)
1558 {
1559 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1560 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1561 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1562 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001563 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001564 return true;
1565
1566 default:
1567 return false;
1568 }
1569}
1570
Jamie Madillc29968b2016-01-20 11:17:23 -05001571bool ValidCompressedImageSize(const ValidationContext *context,
1572 GLenum internalFormat,
1573 GLsizei width,
1574 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001575{
Geoff Lang5d601382014-07-22 15:14:06 -04001576 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1577 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001578 {
1579 return false;
1580 }
1581
Geoff Lang0d8b7242015-09-09 14:56:53 -04001582 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001583 {
1584 return false;
1585 }
1586
Geoff Lang0d8b7242015-09-09 14:56:53 -04001587 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1588 {
1589 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1590 width % formatInfo.compressedBlockWidth != 0) ||
1591 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1592 height % formatInfo.compressedBlockHeight != 0))
1593 {
1594 return false;
1595 }
1596 }
1597
Geoff Langd4f180b2013-09-24 13:57:44 -04001598 return true;
1599}
1600
Geoff Langff5b2d52016-09-07 11:32:23 -04001601bool ValidImageDataSize(ValidationContext *context,
1602 GLenum textureTarget,
1603 GLsizei width,
1604 GLsizei height,
1605 GLsizei depth,
1606 GLenum internalFormat,
1607 GLenum type,
1608 const GLvoid *pixels,
1609 GLsizei imageSize)
1610{
1611 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1612 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1613 {
1614 // Checks are not required
1615 return true;
1616 }
1617
1618 // ...the data would be unpacked from the buffer object such that the memory reads required
1619 // would exceed the data store size.
1620 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1621 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1622 const gl::Extents size(width, height, depth);
1623 const auto &unpack = context->getGLState().getUnpackState();
1624
1625 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1626 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1627 if (endByteOrErr.isError())
1628 {
1629 context->handleError(endByteOrErr.getError());
1630 return false;
1631 }
1632
1633 GLuint endByte = endByteOrErr.getResult();
1634
1635 if (pixelUnpackBuffer)
1636 {
1637 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1638 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1639 checkedEndByte += checkedOffset;
1640
1641 if (!checkedEndByte.IsValid() ||
1642 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1643 {
1644 // Overflow past the end of the buffer
1645 context->handleError(Error(GL_INVALID_OPERATION));
1646 return false;
1647 }
1648 }
1649 else
1650 {
1651 ASSERT(imageSize >= 0);
1652 if (pixels == nullptr && imageSize != 0)
1653 {
1654 context->handleError(
1655 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001656 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001657 }
1658
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001659 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001660 {
1661 context->handleError(
1662 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1663 return false;
1664 }
1665 }
1666
1667 return true;
1668}
1669
Geoff Lang37dde692014-01-31 16:34:54 -05001670bool ValidQueryType(const Context *context, GLenum queryType)
1671{
He Yunchaoced53ae2016-11-29 15:00:51 +08001672 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1673 "GL extension enums not equal.");
1674 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1675 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001676
1677 switch (queryType)
1678 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001679 case GL_ANY_SAMPLES_PASSED:
1680 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1681 return true;
1682 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1683 return (context->getClientMajorVersion() >= 3);
1684 case GL_TIME_ELAPSED_EXT:
1685 return context->getExtensions().disjointTimerQuery;
1686 case GL_COMMANDS_COMPLETED_CHROMIUM:
1687 return context->getExtensions().syncQuery;
1688 default:
1689 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001690 }
1691}
1692
Jamie Madillef300b12016-10-07 15:12:09 -04001693Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001694{
He Yunchaoced53ae2016-11-29 15:00:51 +08001695 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1696 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1697 // or program object and INVALID_OPERATION if the provided name identifies an object
1698 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001699
Dian Xiang769769a2015-09-09 15:20:08 -07001700 Program *validProgram = context->getProgram(id);
1701
1702 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001703 {
Dian Xiang769769a2015-09-09 15:20:08 -07001704 if (context->getShader(id))
1705 {
Jamie Madill437fa652016-05-03 15:13:24 -04001706 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001707 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1708 }
1709 else
1710 {
Jamie Madill437fa652016-05-03 15:13:24 -04001711 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001712 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001713 }
Dian Xiang769769a2015-09-09 15:20:08 -07001714
1715 return validProgram;
1716}
1717
Jamie Madillef300b12016-10-07 15:12:09 -04001718Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001719{
1720 // See ValidProgram for spec details.
1721
1722 Shader *validShader = context->getShader(id);
1723
1724 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001725 {
Dian Xiang769769a2015-09-09 15:20:08 -07001726 if (context->getProgram(id))
1727 {
Jamie Madill437fa652016-05-03 15:13:24 -04001728 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001729 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1730 }
1731 else
1732 {
Jamie Madill437fa652016-05-03 15:13:24 -04001733 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001734 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001735 }
Dian Xiang769769a2015-09-09 15:20:08 -07001736
1737 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001738}
1739
Geoff Langb1196682014-07-23 13:47:29 -04001740bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001741{
1742 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1743 {
1744 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1745
Geoff Langaae65a42014-05-26 12:43:44 -04001746 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001747 {
Jamie Madill437fa652016-05-03 15:13:24 -04001748 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001749 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001750 }
1751 }
1752 else
1753 {
1754 switch (attachment)
1755 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001756 case GL_DEPTH_ATTACHMENT:
1757 case GL_STENCIL_ATTACHMENT:
1758 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001759
He Yunchaoced53ae2016-11-29 15:00:51 +08001760 case GL_DEPTH_STENCIL_ATTACHMENT:
1761 if (!context->getExtensions().webglCompatibility &&
1762 context->getClientMajorVersion() < 3)
1763 {
1764 context->handleError(Error(GL_INVALID_ENUM));
1765 return false;
1766 }
1767 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001768
He Yunchaoced53ae2016-11-29 15:00:51 +08001769 default:
1770 context->handleError(Error(GL_INVALID_ENUM));
1771 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001772 }
1773 }
1774
1775 return true;
1776}
1777
He Yunchaoced53ae2016-11-29 15:00:51 +08001778bool ValidateRenderbufferStorageParametersBase(gl::Context *context,
1779 GLenum target,
1780 GLsizei samples,
1781 GLenum internalformat,
1782 GLsizei width,
1783 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001784{
1785 switch (target)
1786 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001787 case GL_RENDERBUFFER:
1788 break;
1789 default:
1790 context->handleError(Error(GL_INVALID_ENUM));
1791 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001792 }
1793
1794 if (width < 0 || height < 0 || samples < 0)
1795 {
Jamie Madill437fa652016-05-03 15:13:24 -04001796 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001797 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001798 }
1799
Geoff Langd87878e2014-09-19 15:42:59 -04001800 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1801 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001802 {
Jamie Madill437fa652016-05-03 15:13:24 -04001803 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001804 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001805 }
1806
1807 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1808 // 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 -08001809 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001810 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001811 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001812 {
Jamie Madill437fa652016-05-03 15:13:24 -04001813 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001814 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001815 }
1816
Geoff Langaae65a42014-05-26 12:43:44 -04001817 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001818 {
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
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001823 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001824 if (handle == 0)
1825 {
Jamie Madill437fa652016-05-03 15:13:24 -04001826 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001827 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001828 }
1829
1830 return true;
1831}
1832
He Yunchaoced53ae2016-11-29 15:00:51 +08001833bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context,
1834 GLenum target,
1835 GLsizei samples,
1836 GLenum internalformat,
1837 GLsizei width,
1838 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -08001839{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001840 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001841
1842 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001843 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001844 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001845 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001846 {
Jamie Madill437fa652016-05-03 15:13:24 -04001847 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001848 return false;
1849 }
1850
1851 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1852 // the specified storage. This is different than ES 3.0 in which a sample number higher
1853 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001854 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001855 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001856 {
Geoff Langa4903b72015-03-02 16:02:48 -08001857 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1858 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1859 {
Jamie Madill437fa652016-05-03 15:13:24 -04001860 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001861 return false;
1862 }
Corentin Walleze0902642014-11-04 12:32:15 -08001863 }
1864
He Yunchaoced53ae2016-11-29 15:00:51 +08001865 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
1866 width, height);
Corentin Walleze0902642014-11-04 12:32:15 -08001867}
1868
He Yunchaoced53ae2016-11-29 15:00:51 +08001869bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1870 GLenum target,
1871 GLenum attachment,
1872 GLenum renderbuffertarget,
1873 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001874{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001875 if (!ValidFramebufferTarget(target))
1876 {
Jamie Madill437fa652016-05-03 15:13:24 -04001877 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001878 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001879 }
1880
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001881 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001882
Jamie Madill84115c92015-04-23 15:00:07 -04001883 ASSERT(framebuffer);
1884 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001885 {
Jamie Madill437fa652016-05-03 15:13:24 -04001886 context->handleError(
1887 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001888 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001889 }
1890
Jamie Madillb4472272014-07-03 10:38:55 -04001891 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001892 {
Jamie Madillb4472272014-07-03 10:38:55 -04001893 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001894 }
1895
Jamie Madillab9d82c2014-01-21 16:38:14 -05001896 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1897 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1898 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1899 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1900 if (renderbuffer != 0)
1901 {
1902 if (!context->getRenderbuffer(renderbuffer))
1903 {
Jamie Madill437fa652016-05-03 15:13:24 -04001904 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001905 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001906 }
1907 }
1908
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001909 return true;
1910}
1911
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001912bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001913 GLint srcX0,
1914 GLint srcY0,
1915 GLint srcX1,
1916 GLint srcY1,
1917 GLint dstX0,
1918 GLint dstY0,
1919 GLint dstX1,
1920 GLint dstY1,
1921 GLbitfield mask,
1922 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001923{
1924 switch (filter)
1925 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001926 case GL_NEAREST:
1927 break;
1928 case GL_LINEAR:
1929 break;
1930 default:
1931 context->handleError(Error(GL_INVALID_ENUM));
1932 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001933 }
1934
1935 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1936 {
Jamie Madill437fa652016-05-03 15:13:24 -04001937 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001938 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001939 }
1940
1941 if (mask == 0)
1942 {
1943 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1944 // buffers are copied.
1945 return false;
1946 }
1947
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001948 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1949 // color buffer, leaving only nearest being unfiltered from above
1950 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1951 {
Jamie Madill437fa652016-05-03 15:13:24 -04001952 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001953 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001954 }
1955
Jamie Madill51f40ec2016-06-15 14:06:00 -04001956 const auto &glState = context->getGLState();
1957 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1958 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001959
1960 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001961 {
Jamie Madill437fa652016-05-03 15:13:24 -04001962 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001963 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001964 }
1965
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001966 if (readFramebuffer->id() == drawFramebuffer->id())
1967 {
1968 context->handleError(Error(GL_INVALID_OPERATION));
1969 return false;
1970 }
1971
Jamie Madill51f40ec2016-06-15 14:06:00 -04001972 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001973 {
Jamie Madill437fa652016-05-03 15:13:24 -04001974 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001975 return false;
1976 }
1977
Jamie Madill51f40ec2016-06-15 14:06:00 -04001978 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001979 {
Jamie Madill437fa652016-05-03 15:13:24 -04001980 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001981 return false;
1982 }
1983
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001984 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001985 {
Jamie Madill437fa652016-05-03 15:13:24 -04001986 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001987 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001988 }
1989
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001990 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1991
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001992 if (mask & GL_COLOR_BUFFER_BIT)
1993 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001994 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001995 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001996
He Yunchao66a41a22016-12-15 16:45:05 +08001997 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001998 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001999 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002000
Geoff Langa15472a2015-08-11 11:48:03 -04002001 for (size_t drawbufferIdx = 0;
2002 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002003 {
Geoff Langa15472a2015-08-11 11:48:03 -04002004 const FramebufferAttachment *attachment =
2005 drawFramebuffer->getDrawBuffer(drawbufferIdx);
2006 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002007 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002008 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002009
Geoff Langb2f3d052013-08-13 12:49:27 -04002010 // The GL ES 3.0.2 spec (pg 193) states that:
2011 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08002012 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
2013 // as well
2014 // 3) If the read buffer is a signed integer format, the draw buffer must be as
2015 // well
Jamie Madill6163c752015-12-07 16:32:59 -05002016 // Changes with EXT_color_buffer_float:
2017 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04002018 GLenum readComponentType = readFormat.info->componentType;
2019 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002020 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002021 readComponentType == GL_SIGNED_NORMALIZED);
2022 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2023 drawComponentType == GL_SIGNED_NORMALIZED);
2024
2025 if (extensions.colorBufferFloat)
2026 {
2027 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2028 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2029
2030 if (readFixedOrFloat != drawFixedOrFloat)
2031 {
Jamie Madill437fa652016-05-03 15:13:24 -04002032 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002033 "If the read buffer contains fixed-point or "
2034 "floating-point values, the draw buffer "
2035 "must as well."));
2036 return false;
2037 }
2038 }
2039 else if (readFixedPoint != drawFixedPoint)
2040 {
Jamie Madill437fa652016-05-03 15:13:24 -04002041 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002042 "If the read buffer contains fixed-point "
2043 "values, the draw buffer must as well."));
2044 return false;
2045 }
2046
2047 if (readComponentType == GL_UNSIGNED_INT &&
2048 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002049 {
Jamie Madill437fa652016-05-03 15:13:24 -04002050 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002051 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002052 }
2053
Jamie Madill6163c752015-12-07 16:32:59 -05002054 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002055 {
Jamie Madill437fa652016-05-03 15:13:24 -04002056 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002057 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002058 }
2059
Jamie Madilla3944d42016-07-22 22:13:26 -04002060 if (readColorBuffer->getSamples() > 0 &&
2061 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002062 {
Jamie Madill437fa652016-05-03 15:13:24 -04002063 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002064 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002065 }
2066 }
2067 }
2068
Jamie Madilla3944d42016-07-22 22:13:26 -04002069 if ((readFormat.info->componentType == GL_INT ||
2070 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2071 filter == GL_LINEAR)
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 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002076 }
He Yunchao66a41a22016-12-15 16:45:05 +08002077 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2078 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
2079 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
2080 // situation is an application error that would lead to a crash in ANGLE.
2081 else if (drawFramebuffer->hasEnabledDrawBuffer())
2082 {
2083 context->handleError(Error(
2084 GL_INVALID_OPERATION,
2085 "Attempt to read from a missing color attachment of a complete framebuffer."));
2086 return false;
2087 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002088 }
2089
He Yunchaoced53ae2016-11-29 15:00:51 +08002090 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002091 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2092 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002093 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002094 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002095 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002096 const gl::FramebufferAttachment *readBuffer =
2097 readFramebuffer->getAttachment(attachments[i]);
2098 const gl::FramebufferAttachment *drawBuffer =
2099 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002100
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002101 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002102 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002103 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002104 {
Jamie Madill437fa652016-05-03 15:13:24 -04002105 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002106 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002107 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002108
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002109 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002110 {
Jamie Madill437fa652016-05-03 15:13:24 -04002111 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002112 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002113 }
2114 }
He Yunchao66a41a22016-12-15 16:45:05 +08002115 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
2116 else if (drawBuffer)
2117 {
2118 context->handleError(Error(GL_INVALID_OPERATION,
2119 "Attempt to read from a missing depth/stencil "
2120 "attachment of a complete framebuffer."));
2121 return false;
2122 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002123 }
2124 }
2125
2126 return true;
2127}
2128
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002129bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002130 GLint x,
2131 GLint y,
2132 GLsizei width,
2133 GLsizei height,
2134 GLenum format,
2135 GLenum type,
2136 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002137{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002138 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2139}
2140
2141bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2142 GLint x,
2143 GLint y,
2144 GLsizei width,
2145 GLsizei height,
2146 GLenum format,
2147 GLenum type,
2148 GLsizei bufSize,
2149 GLsizei *length,
2150 GLvoid *pixels)
2151{
2152 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002153 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002154 return false;
2155 }
2156
Geoff Lang62fce5b2016-09-30 10:46:35 -04002157 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2158 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002159 {
Geoff Langb1196682014-07-23 13:47:29 -04002160 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002161 }
2162
Geoff Lang62fce5b2016-09-30 10:46:35 -04002163 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002164 {
Geoff Langb1196682014-07-23 13:47:29 -04002165 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002166 }
2167
Jamie Madillc29968b2016-01-20 11:17:23 -05002168 return true;
2169}
2170
2171bool ValidateReadnPixelsEXT(Context *context,
2172 GLint x,
2173 GLint y,
2174 GLsizei width,
2175 GLsizei height,
2176 GLenum format,
2177 GLenum type,
2178 GLsizei bufSize,
2179 GLvoid *pixels)
2180{
2181 if (bufSize < 0)
2182 {
Jamie Madill437fa652016-05-03 15:13:24 -04002183 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002184 return false;
2185 }
2186
Geoff Lang62fce5b2016-09-30 10:46:35 -04002187 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2188 pixels);
2189}
Jamie Madill26e91952014-03-05 15:01:27 -05002190
Geoff Lang62fce5b2016-09-30 10:46:35 -04002191bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2192 GLint x,
2193 GLint y,
2194 GLsizei width,
2195 GLsizei height,
2196 GLenum format,
2197 GLenum type,
2198 GLsizei bufSize,
2199 GLsizei *length,
2200 GLvoid *data)
2201{
2202 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002203 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002204 return false;
2205 }
2206
Geoff Lang62fce5b2016-09-30 10:46:35 -04002207 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002208 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002209 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002210 }
2211
Geoff Lang62fce5b2016-09-30 10:46:35 -04002212 if (!ValidateRobustBufferSize(context, bufSize, *length))
2213 {
2214 return false;
2215 }
2216
2217 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002218}
2219
Olli Etuaho41997e72016-03-10 13:38:39 +02002220bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002221{
2222 if (!context->getExtensions().occlusionQueryBoolean &&
2223 !context->getExtensions().disjointTimerQuery)
2224 {
Jamie Madill437fa652016-05-03 15:13:24 -04002225 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002226 return false;
2227 }
2228
Olli Etuaho41997e72016-03-10 13:38:39 +02002229 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002230}
2231
Olli Etuaho41997e72016-03-10 13:38:39 +02002232bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002233{
2234 if (!context->getExtensions().occlusionQueryBoolean &&
2235 !context->getExtensions().disjointTimerQuery)
2236 {
Jamie Madill437fa652016-05-03 15:13:24 -04002237 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002238 return false;
2239 }
2240
Olli Etuaho41997e72016-03-10 13:38:39 +02002241 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002242}
2243
2244bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002245{
2246 if (!ValidQueryType(context, target))
2247 {
Jamie Madill437fa652016-05-03 15:13:24 -04002248 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002249 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002250 }
2251
2252 if (id == 0)
2253 {
Jamie Madill437fa652016-05-03 15:13:24 -04002254 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002255 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002256 }
2257
2258 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2259 // of zero, if the active query object name for <target> is non-zero (for the
2260 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2261 // the active query for either target is non-zero), if <id> is the name of an
2262 // existing query object whose type does not match <target>, or if <id> is the
2263 // active query object name for any query type, the error INVALID_OPERATION is
2264 // generated.
2265
2266 // Ensure no other queries are active
2267 // NOTE: If other queries than occlusion are supported, we will need to check
2268 // separately that:
2269 // a) The query ID passed is not the current active query for any target/type
2270 // b) There are no active queries for the requested target (and in the case
2271 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2272 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002273
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002274 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002275 {
Jamie Madill437fa652016-05-03 15:13:24 -04002276 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002277 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002278 }
2279
2280 Query *queryObject = context->getQuery(id, true, target);
2281
2282 // check that name was obtained with glGenQueries
2283 if (!queryObject)
2284 {
Jamie Madill437fa652016-05-03 15:13:24 -04002285 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002286 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002287 }
2288
2289 // check for type mismatch
2290 if (queryObject->getType() != target)
2291 {
Jamie Madill437fa652016-05-03 15:13:24 -04002292 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002293 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002294 }
2295
2296 return true;
2297}
2298
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002299bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2300{
2301 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002302 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002303 {
Jamie Madill437fa652016-05-03 15:13:24 -04002304 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002305 return false;
2306 }
2307
2308 return ValidateBeginQueryBase(context, target, id);
2309}
2310
2311bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002312{
2313 if (!ValidQueryType(context, target))
2314 {
Jamie Madill437fa652016-05-03 15:13:24 -04002315 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002316 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002317 }
2318
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002319 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002320
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002321 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002322 {
Jamie Madill437fa652016-05-03 15:13:24 -04002323 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002324 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002325 }
2326
Jamie Madill45c785d2014-05-13 14:09:34 -04002327 return true;
2328}
2329
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002330bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2331{
2332 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002333 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002334 {
Jamie Madill437fa652016-05-03 15:13:24 -04002335 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002336 return false;
2337 }
2338
2339 return ValidateEndQueryBase(context, target);
2340}
2341
2342bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2343{
2344 if (!context->getExtensions().disjointTimerQuery)
2345 {
Jamie Madill437fa652016-05-03 15:13:24 -04002346 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002347 return false;
2348 }
2349
2350 if (target != GL_TIMESTAMP_EXT)
2351 {
Jamie Madill437fa652016-05-03 15:13:24 -04002352 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002353 return false;
2354 }
2355
2356 Query *queryObject = context->getQuery(id, true, target);
2357 if (queryObject == nullptr)
2358 {
Jamie Madill437fa652016-05-03 15:13:24 -04002359 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002360 return false;
2361 }
2362
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002363 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002364 {
Jamie Madill437fa652016-05-03 15:13:24 -04002365 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002366 return false;
2367 }
2368
2369 return true;
2370}
2371
Geoff Lang2186c382016-10-14 10:54:54 -04002372bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002373{
Geoff Lang2186c382016-10-14 10:54:54 -04002374 if (numParams)
2375 {
2376 *numParams = 0;
2377 }
2378
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002379 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2380 {
Jamie Madill437fa652016-05-03 15:13:24 -04002381 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002382 return false;
2383 }
2384
2385 switch (pname)
2386 {
2387 case GL_CURRENT_QUERY_EXT:
2388 if (target == GL_TIMESTAMP_EXT)
2389 {
Jamie Madill437fa652016-05-03 15:13:24 -04002390 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002391 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2392 return false;
2393 }
2394 break;
2395 case GL_QUERY_COUNTER_BITS_EXT:
2396 if (!context->getExtensions().disjointTimerQuery ||
2397 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2398 {
Jamie Madill437fa652016-05-03 15:13:24 -04002399 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002400 return false;
2401 }
2402 break;
2403 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002404 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002405 return false;
2406 }
2407
Geoff Lang2186c382016-10-14 10:54:54 -04002408 if (numParams)
2409 {
2410 // All queries return only one value
2411 *numParams = 1;
2412 }
2413
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002414 return true;
2415}
2416
2417bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2418{
2419 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002420 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002421 {
Jamie Madill437fa652016-05-03 15:13:24 -04002422 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002423 return false;
2424 }
2425
Geoff Lang2186c382016-10-14 10:54:54 -04002426 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002427}
2428
Geoff Lang2186c382016-10-14 10:54:54 -04002429bool ValidateGetQueryivRobustANGLE(Context *context,
2430 GLenum target,
2431 GLenum pname,
2432 GLsizei bufSize,
2433 GLsizei *length,
2434 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002435{
Geoff Lang2186c382016-10-14 10:54:54 -04002436 if (!ValidateRobustEntryPoint(context, bufSize))
2437 {
2438 return false;
2439 }
2440
2441 if (!ValidateGetQueryivBase(context, target, pname, length))
2442 {
2443 return false;
2444 }
2445
2446 if (!ValidateRobustBufferSize(context, bufSize, *length))
2447 {
2448 return false;
2449 }
2450
2451 return true;
2452}
2453
2454bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2455{
2456 if (numParams)
2457 {
2458 *numParams = 0;
2459 }
2460
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002461 Query *queryObject = context->getQuery(id, false, GL_NONE);
2462
2463 if (!queryObject)
2464 {
Jamie Madill437fa652016-05-03 15:13:24 -04002465 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002466 return false;
2467 }
2468
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002469 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002470 {
Jamie Madill437fa652016-05-03 15:13:24 -04002471 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002472 return false;
2473 }
2474
2475 switch (pname)
2476 {
2477 case GL_QUERY_RESULT_EXT:
2478 case GL_QUERY_RESULT_AVAILABLE_EXT:
2479 break;
2480
2481 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002482 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002483 return false;
2484 }
2485
Geoff Lang2186c382016-10-14 10:54:54 -04002486 if (numParams)
2487 {
2488 *numParams = 1;
2489 }
2490
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002491 return true;
2492}
2493
2494bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2495{
2496 if (!context->getExtensions().disjointTimerQuery)
2497 {
Jamie Madill437fa652016-05-03 15:13:24 -04002498 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002499 return false;
2500 }
Geoff Lang2186c382016-10-14 10:54:54 -04002501 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2502}
2503
2504bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2505 GLuint id,
2506 GLenum pname,
2507 GLsizei bufSize,
2508 GLsizei *length,
2509 GLint *params)
2510{
2511 if (!context->getExtensions().disjointTimerQuery)
2512 {
2513 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2514 return false;
2515 }
2516
2517 if (!ValidateRobustEntryPoint(context, bufSize))
2518 {
2519 return false;
2520 }
2521
2522 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2523 {
2524 return false;
2525 }
2526
2527 if (!ValidateRobustBufferSize(context, bufSize, *length))
2528 {
2529 return false;
2530 }
2531
2532 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002533}
2534
2535bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2536{
2537 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002538 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002539 {
Jamie Madill437fa652016-05-03 15:13:24 -04002540 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002541 return false;
2542 }
Geoff Lang2186c382016-10-14 10:54:54 -04002543 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2544}
2545
2546bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2547 GLuint id,
2548 GLenum pname,
2549 GLsizei bufSize,
2550 GLsizei *length,
2551 GLuint *params)
2552{
2553 if (!context->getExtensions().disjointTimerQuery &&
2554 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2555 {
2556 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2557 return false;
2558 }
2559
2560 if (!ValidateRobustEntryPoint(context, bufSize))
2561 {
2562 return false;
2563 }
2564
2565 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2566 {
2567 return false;
2568 }
2569
2570 if (!ValidateRobustBufferSize(context, bufSize, *length))
2571 {
2572 return false;
2573 }
2574
2575 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002576}
2577
2578bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2579{
2580 if (!context->getExtensions().disjointTimerQuery)
2581 {
Jamie Madill437fa652016-05-03 15:13:24 -04002582 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002583 return false;
2584 }
Geoff Lang2186c382016-10-14 10:54:54 -04002585 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2586}
2587
2588bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2589 GLuint id,
2590 GLenum pname,
2591 GLsizei bufSize,
2592 GLsizei *length,
2593 GLint64 *params)
2594{
2595 if (!context->getExtensions().disjointTimerQuery)
2596 {
2597 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2598 return false;
2599 }
2600
2601 if (!ValidateRobustEntryPoint(context, bufSize))
2602 {
2603 return false;
2604 }
2605
2606 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2607 {
2608 return false;
2609 }
2610
2611 if (!ValidateRobustBufferSize(context, bufSize, *length))
2612 {
2613 return false;
2614 }
2615
2616 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002617}
2618
2619bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2620{
2621 if (!context->getExtensions().disjointTimerQuery)
2622 {
Jamie Madill437fa652016-05-03 15:13:24 -04002623 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002624 return false;
2625 }
Geoff Lang2186c382016-10-14 10:54:54 -04002626 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2627}
2628
2629bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2630 GLuint id,
2631 GLenum pname,
2632 GLsizei bufSize,
2633 GLsizei *length,
2634 GLuint64 *params)
2635{
2636 if (!context->getExtensions().disjointTimerQuery)
2637 {
2638 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2639 return false;
2640 }
2641
2642 if (!ValidateRobustEntryPoint(context, bufSize))
2643 {
2644 return false;
2645 }
2646
2647 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2648 {
2649 return false;
2650 }
2651
2652 if (!ValidateRobustBufferSize(context, bufSize, *length))
2653 {
2654 return false;
2655 }
2656
2657 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002658}
2659
Jamie Madill62d31cb2015-09-11 13:25:51 -04002660static bool ValidateUniformCommonBase(gl::Context *context,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002661 gl::Program *program,
Jamie Madill62d31cb2015-09-11 13:25:51 -04002662 GLenum targetUniformType,
2663 GLint location,
2664 GLsizei count,
2665 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002666{
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002667 // TODO(Jiajia): Add image uniform check in future.
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002668 if (count < 0)
2669 {
Jamie Madill437fa652016-05-03 15:13:24 -04002670 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002671 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002672 }
2673
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002674 if (!program || !program->isLinked())
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002675 {
Jamie Madill437fa652016-05-03 15:13:24 -04002676 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002677 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002678 }
2679
Geoff Langd8605522016-04-13 10:19:12 -04002680 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002681 {
2682 // Silently ignore the uniform command
2683 return false;
2684 }
2685
Geoff Lang7dd2e102014-11-10 15:19:26 -05002686 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002687 {
Jamie Madill437fa652016-05-03 15:13:24 -04002688 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002689 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002690 }
2691
Jamie Madill62d31cb2015-09-11 13:25:51 -04002692 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002693
2694 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002695 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002696 {
Jamie Madill437fa652016-05-03 15:13:24 -04002697 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002698 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002699 }
2700
Jamie Madill62d31cb2015-09-11 13:25:51 -04002701 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002702 return true;
2703}
2704
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002705bool ValidateProgramUniform(gl::Context *context,
2706 GLenum uniformType,
2707 GLuint program,
2708 GLint location,
2709 GLsizei count)
2710{
2711 // Check for ES31 program uniform entry points
2712 if (context->getClientVersion() < Version(3, 1))
2713 {
2714 context->handleError(Error(GL_INVALID_OPERATION));
2715 return false;
2716 }
2717
2718 const LinkedUniform *uniform = nullptr;
2719 gl::Program *programObject = GetValidProgram(context, program);
2720 if (!ValidateUniformCommonBase(context, programObject, uniformType, location, count, &uniform))
2721 {
2722 return false;
2723 }
2724
2725 GLenum targetBoolType = VariableBoolVectorType(uniformType);
2726 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
2727 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2728 {
2729 context->handleError(Error(GL_INVALID_OPERATION));
2730 return false;
2731 }
2732
2733 return true;
2734}
2735
2736bool ValidateProgramUniformMatrix(gl::Context *context,
2737 GLenum matrixType,
2738 GLuint program,
2739 GLint location,
2740 GLsizei count,
2741 GLboolean transpose)
2742{
2743 // Check for ES31 program uniform entry points
2744 if (context->getClientVersion() < Version(3, 1))
2745 {
2746 context->handleError(Error(GL_INVALID_OPERATION));
2747 return false;
2748 }
2749
2750 const LinkedUniform *uniform = nullptr;
2751 gl::Program *programObject = GetValidProgram(context, program);
2752 if (!ValidateUniformCommonBase(context, programObject, matrixType, location, count, &uniform))
2753 {
2754 return false;
2755 }
2756
2757 if (uniform->type != matrixType)
2758 {
2759 context->handleError(Error(GL_INVALID_OPERATION));
2760 return false;
2761 }
2762
2763 return true;
2764}
2765
Jamie Madillaa981bd2014-05-20 10:55:55 -04002766bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2767{
2768 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002769 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2770 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002771 {
Jamie Madill437fa652016-05-03 15:13:24 -04002772 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002773 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002774 }
2775
Jamie Madill62d31cb2015-09-11 13:25:51 -04002776 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002777 gl::Program *program = context->getGLState().getProgram();
2778 if (!ValidateUniformCommonBase(context, program, uniformType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002779 {
2780 return false;
2781 }
2782
He Yunchaoced53ae2016-11-29 15:00:51 +08002783 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002784 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002785 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2786 {
Jamie Madill437fa652016-05-03 15:13:24 -04002787 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002788 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002789 }
2790
2791 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002792}
2793
He Yunchaoced53ae2016-11-29 15:00:51 +08002794bool ValidateUniformMatrix(gl::Context *context,
2795 GLenum matrixType,
2796 GLint location,
2797 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002798 GLboolean transpose)
2799{
2800 // Check for ES3 uniform entry points
2801 int rows = VariableRowCount(matrixType);
2802 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002803 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002804 {
Jamie Madill437fa652016-05-03 15:13:24 -04002805 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002806 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002807 }
2808
Martin Radev1be913c2016-07-11 17:59:16 +03002809 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002810 {
Jamie Madill437fa652016-05-03 15:13:24 -04002811 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002812 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002813 }
2814
Jamie Madill62d31cb2015-09-11 13:25:51 -04002815 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002816 gl::Program *program = context->getGLState().getProgram();
2817 if (!ValidateUniformCommonBase(context, program, matrixType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002818 {
2819 return false;
2820 }
2821
2822 if (uniform->type != matrixType)
2823 {
Jamie Madill437fa652016-05-03 15:13:24 -04002824 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002825 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002826 }
2827
2828 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002829}
2830
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002831bool ValidateStateQuery(ValidationContext *context,
2832 GLenum pname,
2833 GLenum *nativeType,
2834 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002835{
2836 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2837 {
Jamie Madill437fa652016-05-03 15:13:24 -04002838 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002839 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002840 }
2841
Jamie Madill0af26e12015-03-05 19:54:33 -05002842 const Caps &caps = context->getCaps();
2843
Jamie Madill893ab082014-05-16 16:56:10 -04002844 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2845 {
2846 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2847
Jamie Madill0af26e12015-03-05 19:54:33 -05002848 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002849 {
Jamie Madill437fa652016-05-03 15:13:24 -04002850 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002851 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002852 }
2853 }
2854
2855 switch (pname)
2856 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002857 case GL_TEXTURE_BINDING_2D:
2858 case GL_TEXTURE_BINDING_CUBE_MAP:
2859 case GL_TEXTURE_BINDING_3D:
2860 case GL_TEXTURE_BINDING_2D_ARRAY:
2861 break;
2862 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2863 if (!context->getExtensions().eglStreamConsumerExternal &&
2864 !context->getExtensions().eglImageExternal)
2865 {
2866 context->handleError(Error(GL_INVALID_ENUM,
2867 "Neither NV_EGL_stream_consumer_external nor "
2868 "GL_OES_EGL_image_external extensions enabled"));
2869 return false;
2870 }
2871 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002872
He Yunchaoced53ae2016-11-29 15:00:51 +08002873 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2874 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002875 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002876 if (context->getGLState().getReadFramebuffer()->checkStatus(
2877 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002878 {
Jamie Madill437fa652016-05-03 15:13:24 -04002879 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002880 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002881 }
2882
Jamie Madill51f40ec2016-06-15 14:06:00 -04002883 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2884 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002885
2886 if (framebuffer->getReadBufferState() == GL_NONE)
2887 {
2888 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2889 return false;
2890 }
2891
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002892 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002893 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002894 {
Jamie Madill437fa652016-05-03 15:13:24 -04002895 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002896 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002897 }
2898 }
2899 break;
2900
He Yunchaoced53ae2016-11-29 15:00:51 +08002901 default:
2902 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002903 }
2904
2905 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002906 if (*numParams == 0)
2907 {
2908 return false;
2909 }
2910
2911 return true;
2912}
2913
2914bool ValidateRobustStateQuery(ValidationContext *context,
2915 GLenum pname,
2916 GLsizei bufSize,
2917 GLenum *nativeType,
2918 unsigned int *numParams)
2919{
2920 if (!ValidateRobustEntryPoint(context, bufSize))
2921 {
2922 return false;
2923 }
2924
2925 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2926 {
2927 return false;
2928 }
2929
2930 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002931 {
2932 return false;
2933 }
2934
2935 return true;
2936}
2937
Jamie Madillc29968b2016-01-20 11:17:23 -05002938bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2939 GLenum target,
2940 GLint level,
2941 GLenum internalformat,
2942 bool isSubImage,
2943 GLint xoffset,
2944 GLint yoffset,
2945 GLint zoffset,
2946 GLint x,
2947 GLint y,
2948 GLsizei width,
2949 GLsizei height,
2950 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002951 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002952{
Jamie Madill560a8d82014-05-21 13:06:20 -04002953 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2954 {
Jamie Madill437fa652016-05-03 15:13:24 -04002955 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002956 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002957 }
2958
He Yunchaoced53ae2016-11-29 15:00:51 +08002959 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2960 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002961 {
Jamie Madill437fa652016-05-03 15:13:24 -04002962 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002963 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002964 }
2965
2966 if (border != 0)
2967 {
Jamie Madill437fa652016-05-03 15:13:24 -04002968 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002969 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002970 }
2971
2972 if (!ValidMipLevel(context, target, level))
2973 {
Jamie Madill437fa652016-05-03 15:13:24 -04002974 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002975 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002976 }
2977
Jamie Madill51f40ec2016-06-15 14:06:00 -04002978 const auto &state = context->getGLState();
2979 auto readFramebuffer = state.getReadFramebuffer();
2980 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002981 {
Jamie Madill437fa652016-05-03 15:13:24 -04002982 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002983 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002984 }
2985
Jamie Madill51f40ec2016-06-15 14:06:00 -04002986 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002987 {
Jamie Madill437fa652016-05-03 15:13:24 -04002988 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002989 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002990 }
2991
Martin Radev138064f2016-07-15 12:03:41 +03002992 if (readFramebuffer->getReadBufferState() == GL_NONE)
2993 {
2994 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2995 return false;
2996 }
2997
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002998 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2999 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08003000 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05003001 // situation is an application error that would lead to a crash in ANGLE.
3002 if (readFramebuffer->getReadColorbuffer() == nullptr)
3003 {
3004 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
3005 return false;
3006 }
3007
Geoff Langaae65a42014-05-26 12:43:44 -04003008 const gl::Caps &caps = context->getCaps();
3009
Geoff Langaae65a42014-05-26 12:43:44 -04003010 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04003011 switch (target)
3012 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003013 case GL_TEXTURE_2D:
3014 maxDimension = caps.max2DTextureSize;
3015 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003016
He Yunchaoced53ae2016-11-29 15:00:51 +08003017 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3018 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3019 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3020 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3021 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3022 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3023 maxDimension = caps.maxCubeMapTextureSize;
3024 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003025
He Yunchaoced53ae2016-11-29 15:00:51 +08003026 case GL_TEXTURE_2D_ARRAY:
3027 maxDimension = caps.max2DTextureSize;
3028 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003029
He Yunchaoced53ae2016-11-29 15:00:51 +08003030 case GL_TEXTURE_3D:
3031 maxDimension = caps.max3DTextureSize;
3032 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04003033
He Yunchaoced53ae2016-11-29 15:00:51 +08003034 default:
3035 context->handleError(Error(GL_INVALID_ENUM));
3036 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003037 }
3038
Jamie Madillc29968b2016-01-20 11:17:23 -05003039 gl::Texture *texture =
3040 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003041 if (!texture)
3042 {
Jamie Madill437fa652016-05-03 15:13:24 -04003043 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003044 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003045 }
3046
Geoff Lang69cce582015-09-17 13:20:36 -04003047 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003048 {
Jamie Madill437fa652016-05-03 15:13:24 -04003049 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003050 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003051 }
3052
Geoff Lang5d601382014-07-22 15:14:06 -04003053 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3054
3055 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003056 {
Jamie Madill437fa652016-05-03 15:13:24 -04003057 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003058 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003059 }
3060
Geoff Langa9be0dc2014-12-17 12:34:40 -05003061 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003062 {
Jamie Madill437fa652016-05-03 15:13:24 -04003063 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003064 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003065 }
3066
3067 if (isSubImage)
3068 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003069 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3070 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3071 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003072 {
Jamie Madill437fa652016-05-03 15:13:24 -04003073 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003074 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003075 }
3076 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003077 else
3078 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003079 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003080 {
Jamie Madill437fa652016-05-03 15:13:24 -04003081 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003082 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003083 }
3084
Geoff Langeb66a6e2016-10-31 13:06:12 -04003085 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003086 {
Jamie Madill437fa652016-05-03 15:13:24 -04003087 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003088 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003089 }
3090
3091 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003092 if (static_cast<int>(width) > maxLevelDimension ||
3093 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003094 {
Jamie Madill437fa652016-05-03 15:13:24 -04003095 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003096 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003097 }
3098 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003099
Jamie Madill0c8abca2016-07-22 20:21:26 -04003100 if (textureFormatOut)
3101 {
3102 *textureFormatOut = texture->getFormat(target, level);
3103 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003104 return true;
3105}
3106
Jiajia Qind9671222016-11-29 16:30:31 +08003107bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003108{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003109 switch (mode)
3110 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003111 case GL_POINTS:
3112 case GL_LINES:
3113 case GL_LINE_LOOP:
3114 case GL_LINE_STRIP:
3115 case GL_TRIANGLES:
3116 case GL_TRIANGLE_STRIP:
3117 case GL_TRIANGLE_FAN:
3118 break;
3119 default:
3120 context->handleError(Error(GL_INVALID_ENUM));
3121 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003122 }
3123
Jamie Madill250d33f2014-06-06 17:09:03 -04003124 if (count < 0)
3125 {
Jamie Madill437fa652016-05-03 15:13:24 -04003126 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003127 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003128 }
3129
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003130 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003131
Jamie Madill250d33f2014-06-06 17:09:03 -04003132 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003133 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003134 {
Jamie Madill437fa652016-05-03 15:13:24 -04003135 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003136 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003137 }
3138
Jamie Madillcbcde722017-01-06 14:50:00 -05003139 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3140 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04003141 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003142 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
3143 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04003144 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003145 const FramebufferAttachment *dsAttachment =
3146 framebuffer->getStencilOrDepthStencilAttachment();
3147 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08003148 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003149 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05003150
3151 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
3152 bool differentWritemasks =
3153 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3154 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
3155 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3156 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
3157
3158 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04003159 {
Jamie Madillcbcde722017-01-06 14:50:00 -05003160 if (!context->getExtensions().webglCompatibility)
3161 {
Jamie Madill6a6b09c2017-01-12 21:52:29 +00003162 ERR("This ANGLE implementation does not support separate front/back stencil "
3163 "writemasks, reference values, or stencil mask values.");
Jamie Madillcbcde722017-01-06 14:50:00 -05003164 }
Jamie Madill437fa652016-05-03 15:13:24 -04003165 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003166 return false;
3167 }
Jamie Madillac528012014-06-20 13:21:23 -04003168 }
3169
Jamie Madill51f40ec2016-06-15 14:06:00 -04003170 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003171 {
Jamie Madill437fa652016-05-03 15:13:24 -04003172 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003173 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003174 }
3175
Geoff Lang7dd2e102014-11-10 15:19:26 -05003176 gl::Program *program = state.getProgram();
3177 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003178 {
Jamie Madill437fa652016-05-03 15:13:24 -04003179 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003180 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003181 }
3182
Geoff Lang7dd2e102014-11-10 15:19:26 -05003183 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003184 {
Jamie Madill437fa652016-05-03 15:13:24 -04003185 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003186 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003187 }
3188
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003189 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003190 for (unsigned int uniformBlockIndex = 0;
3191 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003192 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003193 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003194 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003195 const OffsetBindingPointer<Buffer> &uniformBuffer =
3196 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003197
Geoff Lang5d124a62015-09-15 13:03:27 -04003198 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003199 {
3200 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003201 context->handleError(
3202 Error(GL_INVALID_OPERATION,
3203 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003204 return false;
3205 }
3206
Geoff Lang5d124a62015-09-15 13:03:27 -04003207 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003208 if (uniformBufferSize == 0)
3209 {
3210 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003211 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003212 }
3213
Jamie Madill62d31cb2015-09-11 13:25:51 -04003214 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003215 {
3216 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003217 context->handleError(
3218 Error(GL_INVALID_OPERATION,
3219 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003220 return false;
3221 }
3222 }
3223
Jamie Madilla4595b82017-01-11 17:36:34 -05003224 // Detect rendering feedback loops for WebGL.
3225 if (context->getExtensions().webglCompatibility)
3226 {
3227 if (framebuffer->formsRenderingFeedbackLoopWith(state))
3228 {
3229 context->handleError(
3230 Error(GL_INVALID_OPERATION,
3231 "Rendering feedback loop formed between Framebuffer and active Texture."));
3232 return false;
3233 }
3234 }
3235
Jamie Madill250d33f2014-06-06 17:09:03 -04003236 // No-op if zero count
3237 return (count > 0);
3238}
3239
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003240bool ValidateDrawArrays(ValidationContext *context,
3241 GLenum mode,
3242 GLint first,
3243 GLsizei count,
3244 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003245{
Jamie Madillfd716582014-06-06 17:09:04 -04003246 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003247 {
Jamie Madill437fa652016-05-03 15:13:24 -04003248 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003249 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003250 }
3251
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003252 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003253 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003254 if (curTransformFeedback && curTransformFeedback->isActive() &&
3255 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003256 {
3257 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003258 // that does not match the current transform feedback object's draw mode (if transform
3259 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003260 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003261 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003262 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003263 }
3264
Jiajia Qind9671222016-11-29 16:30:31 +08003265 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003266 {
3267 return false;
3268 }
3269
Corentin Wallez71168a02016-12-19 15:11:18 -08003270 // Check the computation of maxVertex doesn't overflow.
3271 // - first < 0 or count < 0 have been checked as an error condition
3272 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3273 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3274 ASSERT(count > 0 && first >= 0);
3275 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3276 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003277 {
3278 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3279 return false;
3280 }
3281
Corentin Wallez71168a02016-12-19 15:11:18 -08003282 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003283 {
3284 return false;
3285 }
3286
3287 return true;
3288}
3289
He Yunchaoced53ae2016-11-29 15:00:51 +08003290bool ValidateDrawArraysInstanced(Context *context,
3291 GLenum mode,
3292 GLint first,
3293 GLsizei count,
3294 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003295{
3296 if (primcount < 0)
3297 {
Jamie Madill437fa652016-05-03 15:13:24 -04003298 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003299 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003300 }
3301
Jamie Madill2b976812014-08-25 15:47:49 -04003302 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003303 {
3304 return false;
3305 }
3306
3307 // No-op if zero primitive count
3308 return (primcount > 0);
3309}
3310
Geoff Lang87a93302014-09-16 13:29:43 -04003311static bool ValidateDrawInstancedANGLE(Context *context)
3312{
3313 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003314 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003315
Geoff Lang7dd2e102014-11-10 15:19:26 -05003316 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003317
3318 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003319 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003320 {
3321 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003322 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003323 {
3324 return true;
3325 }
3326 }
3327
Jamie Madill437fa652016-05-03 15:13:24 -04003328 context->handleError(Error(GL_INVALID_OPERATION,
3329 "ANGLE_instanced_arrays requires that at least one active attribute"
3330 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003331 return false;
3332}
3333
He Yunchaoced53ae2016-11-29 15:00:51 +08003334bool ValidateDrawArraysInstancedANGLE(Context *context,
3335 GLenum mode,
3336 GLint first,
3337 GLsizei count,
3338 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003339{
3340 if (!ValidateDrawInstancedANGLE(context))
3341 {
3342 return false;
3343 }
3344
3345 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3346}
3347
Jiajia Qind9671222016-11-29 16:30:31 +08003348bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003349{
Jamie Madill250d33f2014-06-06 17:09:03 -04003350 switch (type)
3351 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003352 case GL_UNSIGNED_BYTE:
3353 case GL_UNSIGNED_SHORT:
3354 break;
3355 case GL_UNSIGNED_INT:
3356 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3357 {
3358 context->handleError(Error(GL_INVALID_ENUM));
3359 return false;
3360 }
3361 break;
3362 default:
3363 context->handleError(Error(GL_INVALID_ENUM));
3364 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003365 }
3366
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003367 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003368
3369 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003370 if (curTransformFeedback && curTransformFeedback->isActive() &&
3371 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003372 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003373 // It is an invalid operation to call DrawElements, DrawRangeElements or
3374 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003375 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003376 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003377 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003378 }
3379
Jiajia Qind9671222016-11-29 16:30:31 +08003380 return true;
3381}
3382
3383bool ValidateDrawElements(ValidationContext *context,
3384 GLenum mode,
3385 GLsizei count,
3386 GLenum type,
3387 const GLvoid *indices,
3388 GLsizei primcount,
3389 IndexRange *indexRangeOut)
3390{
3391 if (!ValidateDrawElementsBase(context, type))
3392 return false;
3393
3394 const State &state = context->getGLState();
3395
Jamie Madill250d33f2014-06-06 17:09:03 -04003396 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003397 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003398 {
Jamie Madill437fa652016-05-03 15:13:24 -04003399 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003400 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003401 }
3402
He Yunchaoced53ae2016-11-29 15:00:51 +08003403 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003404 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003405
Jamie Madillae3000b2014-08-25 15:47:51 -04003406 if (elementArrayBuffer)
3407 {
3408 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3409
3410 GLint64 offset = reinterpret_cast<GLint64>(indices);
He Yunchaoced53ae2016-11-29 15:00:51 +08003411 GLint64 byteCount =
3412 static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count) + offset;
Jamie Madillae3000b2014-08-25 15:47:51 -04003413
3414 // check for integer overflows
3415 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3416 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3417 {
Jamie Madill437fa652016-05-03 15:13:24 -04003418 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003419 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003420 }
3421
3422 // Check for reading past the end of the bound buffer object
3423 if (byteCount > elementArrayBuffer->getSize())
3424 {
Jamie Madill437fa652016-05-03 15:13:24 -04003425 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003426 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003427 }
3428 }
Corentin Wallez327411e2016-12-09 11:09:17 -05003429 else if (context->getExtensions().webglCompatibility && count > 0)
3430 {
3431 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3432 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3433 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3434 context->handleError(
3435 Error(GL_INVALID_OPERATION, "There is no element array buffer bound and count > 0."));
3436 return false;
3437 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003438 else if (!indices)
3439 {
Corentin Wallez327411e2016-12-09 11:09:17 -05003440 // This is an application error that would normally result in a crash,
3441 // but we catch it and return an error
3442 context->handleError(
3443 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003444 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003445 }
3446
Jiajia Qind9671222016-11-29 16:30:31 +08003447 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003448 {
3449 return false;
3450 }
3451
Jamie Madill2b976812014-08-25 15:47:49 -04003452 // Use max index to validate if our vertex buffers are large enough for the pull.
3453 // TODO: offer fast path, with disabled index validation.
3454 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3455 if (elementArrayBuffer)
3456 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003457 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003458 Error error =
3459 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3460 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003461 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003462 {
Jamie Madill437fa652016-05-03 15:13:24 -04003463 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003464 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003465 }
3466 }
3467 else
3468 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003469 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003470 }
3471
Jamie Madille79b1e12015-11-04 16:36:37 -05003472 // If we use an index greater than our maximum supported index range, return an error.
3473 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3474 // return an error if possible here.
3475 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3476 {
Jamie Madill437fa652016-05-03 15:13:24 -04003477 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003478 return false;
3479 }
3480
Corentin Wallez92db6942016-12-09 13:10:36 -05003481 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3482 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003483 {
3484 return false;
3485 }
3486
Geoff Lang3edfe032015-09-04 16:38:24 -04003487 // No op if there are no real indices in the index data (all are primitive restart).
3488 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003489}
3490
Geoff Langb1196682014-07-23 13:47:29 -04003491bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003492 GLenum mode,
3493 GLsizei count,
3494 GLenum type,
3495 const GLvoid *indices,
3496 GLsizei primcount,
3497 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003498{
3499 if (primcount < 0)
3500 {
Jamie Madill437fa652016-05-03 15:13:24 -04003501 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003502 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003503 }
3504
Jamie Madill2b976812014-08-25 15:47:49 -04003505 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003506 {
3507 return false;
3508 }
3509
3510 // No-op zero primitive count
3511 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003512}
3513
Geoff Lang3edfe032015-09-04 16:38:24 -04003514bool ValidateDrawElementsInstancedANGLE(Context *context,
3515 GLenum mode,
3516 GLsizei count,
3517 GLenum type,
3518 const GLvoid *indices,
3519 GLsizei primcount,
3520 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003521{
3522 if (!ValidateDrawInstancedANGLE(context))
3523 {
3524 return false;
3525 }
3526
He Yunchaoced53ae2016-11-29 15:00:51 +08003527 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3528 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003529}
3530
He Yunchaoced53ae2016-11-29 15:00:51 +08003531bool ValidateFramebufferTextureBase(Context *context,
3532 GLenum target,
3533 GLenum attachment,
3534 GLuint texture,
3535 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003536{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003537 if (!ValidFramebufferTarget(target))
3538 {
Jamie Madill437fa652016-05-03 15:13:24 -04003539 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003540 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003541 }
3542
3543 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003544 {
3545 return false;
3546 }
3547
Jamie Madill55ec3b12014-07-03 10:38:57 -04003548 if (texture != 0)
3549 {
3550 gl::Texture *tex = context->getTexture(texture);
3551
3552 if (tex == NULL)
3553 {
Jamie Madill437fa652016-05-03 15:13:24 -04003554 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003555 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003556 }
3557
3558 if (level < 0)
3559 {
Jamie Madill437fa652016-05-03 15:13:24 -04003560 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003561 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003562 }
3563 }
3564
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003565 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003566 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003567
Jamie Madill84115c92015-04-23 15:00:07 -04003568 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003569 {
Jamie Madill437fa652016-05-03 15:13:24 -04003570 context->handleError(
3571 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003572 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003573 }
3574
3575 return true;
3576}
3577
He Yunchaoced53ae2016-11-29 15:00:51 +08003578bool ValidateFramebufferTexture2D(Context *context,
3579 GLenum target,
3580 GLenum attachment,
3581 GLenum textarget,
3582 GLuint texture,
3583 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003584{
He Yunchaoced53ae2016-11-29 15:00:51 +08003585 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3586 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003587 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3588 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003589 {
Jamie Madill437fa652016-05-03 15:13:24 -04003590 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003591 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003592 }
3593
3594 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
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 ASSERT(tex);
3603
Jamie Madill2a6564e2014-07-11 09:53:19 -04003604 const gl::Caps &caps = context->getCaps();
3605
Jamie Madill55ec3b12014-07-03 10:38:57 -04003606 switch (textarget)
3607 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003608 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003609 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003610 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003611 {
Jamie Madill437fa652016-05-03 15:13:24 -04003612 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003613 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003614 }
3615 if (tex->getTarget() != GL_TEXTURE_2D)
3616 {
Jamie Madill437fa652016-05-03 15:13:24 -04003617 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003618 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003619 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003620 }
3621 break;
3622
He Yunchaoced53ae2016-11-29 15:00:51 +08003623 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3624 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3625 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3626 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3627 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3628 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003629 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003630 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003631 {
Jamie Madill437fa652016-05-03 15:13:24 -04003632 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003633 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003634 }
3635 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3636 {
Jamie Madill437fa652016-05-03 15:13:24 -04003637 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003638 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003639 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003640 }
3641 break;
3642
He Yunchaoced53ae2016-11-29 15:00:51 +08003643 default:
3644 context->handleError(Error(GL_INVALID_ENUM));
3645 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003646 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003647
Jamie Madilla3944d42016-07-22 22:13:26 -04003648 const Format &format = tex->getFormat(textarget, level);
3649 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003650 {
Jamie Madill437fa652016-05-03 15:13:24 -04003651 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003652 return false;
3653 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003654 }
3655
Jamie Madill570f7c82014-07-03 10:38:54 -04003656 return true;
3657}
3658
Geoff Langb1196682014-07-23 13:47:29 -04003659bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003660{
3661 if (program == 0)
3662 {
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 Madill0063c512014-08-25 15:47:53 -04003665 }
3666
Dian Xiang769769a2015-09-09 15:20:08 -07003667 gl::Program *programObject = GetValidProgram(context, program);
3668 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003669 {
3670 return false;
3671 }
3672
Jamie Madill0063c512014-08-25 15:47:53 -04003673 if (!programObject || !programObject->isLinked())
3674 {
Jamie Madill437fa652016-05-03 15:13:24 -04003675 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003676 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003677 }
3678
Geoff Lang7dd2e102014-11-10 15:19:26 -05003679 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003680 {
Jamie Madill437fa652016-05-03 15:13:24 -04003681 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003682 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003683 }
3684
Jamie Madill0063c512014-08-25 15:47:53 -04003685 return true;
3686}
3687
He Yunchaoced53ae2016-11-29 15:00:51 +08003688bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003689{
3690 return ValidateGetUniformBase(context, program, location);
3691}
3692
He Yunchaoced53ae2016-11-29 15:00:51 +08003693bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003694{
Jamie Madill78f41802014-08-25 15:47:55 -04003695 return ValidateGetUniformBase(context, program, location);
3696}
3697
Geoff Langf41d0ee2016-10-07 13:04:23 -04003698static bool ValidateSizedGetUniform(Context *context,
3699 GLuint program,
3700 GLint location,
3701 GLsizei bufSize,
3702 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003703{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003704 if (length)
3705 {
3706 *length = 0;
3707 }
3708
Jamie Madill78f41802014-08-25 15:47:55 -04003709 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003710 {
Jamie Madill78f41802014-08-25 15:47:55 -04003711 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003712 }
3713
Geoff Langf41d0ee2016-10-07 13:04:23 -04003714 if (bufSize < 0)
3715 {
3716 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3717 return false;
3718 }
3719
Jamie Madilla502c742014-08-28 17:19:13 -04003720 gl::Program *programObject = context->getProgram(program);
3721 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003722
Jamie Madill78f41802014-08-25 15:47:55 -04003723 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003724 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003725 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003726 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003727 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003728 context->handleError(
3729 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003730 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003731 }
3732
Geoff Langf41d0ee2016-10-07 13:04:23 -04003733 if (length)
3734 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003735 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003736 }
3737
Jamie Madill0063c512014-08-25 15:47:53 -04003738 return true;
3739}
3740
He Yunchaoced53ae2016-11-29 15:00:51 +08003741bool ValidateGetnUniformfvEXT(Context *context,
3742 GLuint program,
3743 GLint location,
3744 GLsizei bufSize,
3745 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003746{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003747 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003748}
3749
He Yunchaoced53ae2016-11-29 15:00:51 +08003750bool ValidateGetnUniformivEXT(Context *context,
3751 GLuint program,
3752 GLint location,
3753 GLsizei bufSize,
3754 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003755{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003756 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3757}
3758
3759bool ValidateGetUniformfvRobustANGLE(Context *context,
3760 GLuint program,
3761 GLint location,
3762 GLsizei bufSize,
3763 GLsizei *length,
3764 GLfloat *params)
3765{
3766 if (!ValidateRobustEntryPoint(context, bufSize))
3767 {
3768 return false;
3769 }
3770
3771 // bufSize is validated in ValidateSizedGetUniform
3772 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3773}
3774
3775bool ValidateGetUniformivRobustANGLE(Context *context,
3776 GLuint program,
3777 GLint location,
3778 GLsizei bufSize,
3779 GLsizei *length,
3780 GLint *params)
3781{
3782 if (!ValidateRobustEntryPoint(context, bufSize))
3783 {
3784 return false;
3785 }
3786
3787 // bufSize is validated in ValidateSizedGetUniform
3788 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3789}
3790
3791bool ValidateGetUniformuivRobustANGLE(Context *context,
3792 GLuint program,
3793 GLint location,
3794 GLsizei bufSize,
3795 GLsizei *length,
3796 GLuint *params)
3797{
3798 if (!ValidateRobustEntryPoint(context, bufSize))
3799 {
3800 return false;
3801 }
3802
3803 if (context->getClientMajorVersion() < 3)
3804 {
3805 context->handleError(
3806 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3807 return false;
3808 }
3809
3810 // bufSize is validated in ValidateSizedGetUniform
3811 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003812}
3813
He Yunchaoced53ae2016-11-29 15:00:51 +08003814bool ValidateDiscardFramebufferBase(Context *context,
3815 GLenum target,
3816 GLsizei numAttachments,
3817 const GLenum *attachments,
3818 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003819{
3820 if (numAttachments < 0)
3821 {
Jamie Madill437fa652016-05-03 15:13:24 -04003822 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003823 return false;
3824 }
3825
3826 for (GLsizei i = 0; i < numAttachments; ++i)
3827 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003828 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003829 {
3830 if (defaultFramebuffer)
3831 {
Jamie Madill437fa652016-05-03 15:13:24 -04003832 context->handleError(Error(
3833 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003834 return false;
3835 }
3836
3837 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3838 {
Jamie Madill437fa652016-05-03 15:13:24 -04003839 context->handleError(Error(GL_INVALID_OPERATION,
3840 "Requested color attachment is greater than the maximum "
3841 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003842 return false;
3843 }
3844 }
3845 else
3846 {
3847 switch (attachments[i])
3848 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003849 case GL_DEPTH_ATTACHMENT:
3850 case GL_STENCIL_ATTACHMENT:
3851 case GL_DEPTH_STENCIL_ATTACHMENT:
3852 if (defaultFramebuffer)
3853 {
3854 context->handleError(
3855 Error(GL_INVALID_ENUM,
3856 "Invalid attachment when the default framebuffer is bound"));
3857 return false;
3858 }
3859 break;
3860 case GL_COLOR:
3861 case GL_DEPTH:
3862 case GL_STENCIL:
3863 if (!defaultFramebuffer)
3864 {
3865 context->handleError(
3866 Error(GL_INVALID_ENUM,
3867 "Invalid attachment when the default framebuffer is not bound"));
3868 return false;
3869 }
3870 break;
3871 default:
3872 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003873 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003874 }
3875 }
3876 }
3877
3878 return true;
3879}
3880
Austin Kinross6ee1e782015-05-29 17:05:37 -07003881bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3882{
3883 // Note that debug marker calls must not set error state
3884
3885 if (length < 0)
3886 {
3887 return false;
3888 }
3889
3890 if (marker == nullptr)
3891 {
3892 return false;
3893 }
3894
3895 return true;
3896}
3897
3898bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3899{
3900 // Note that debug marker calls must not set error state
3901
3902 if (length < 0)
3903 {
3904 return false;
3905 }
3906
3907 if (length > 0 && marker == nullptr)
3908 {
3909 return false;
3910 }
3911
3912 return true;
3913}
3914
Geoff Langdcab33b2015-07-21 13:03:16 -04003915bool ValidateEGLImageTargetTexture2DOES(Context *context,
3916 egl::Display *display,
3917 GLenum target,
3918 egl::Image *image)
3919{
Geoff Langa8406172015-07-21 16:53:39 -04003920 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3921 {
Jamie Madill437fa652016-05-03 15:13:24 -04003922 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003923 return false;
3924 }
3925
3926 switch (target)
3927 {
3928 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003929 if (!context->getExtensions().eglImage)
3930 {
3931 context->handleError(Error(
3932 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3933 }
3934 break;
3935
3936 case GL_TEXTURE_EXTERNAL_OES:
3937 if (!context->getExtensions().eglImageExternal)
3938 {
3939 context->handleError(Error(
3940 GL_INVALID_ENUM,
3941 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3942 }
Geoff Langa8406172015-07-21 16:53:39 -04003943 break;
3944
3945 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003946 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003947 return false;
3948 }
3949
3950 if (!display->isValidImage(image))
3951 {
Jamie Madill437fa652016-05-03 15:13:24 -04003952 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003953 return false;
3954 }
3955
3956 if (image->getSamples() > 0)
3957 {
Jamie Madill437fa652016-05-03 15:13:24 -04003958 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003959 "cannot create a 2D texture from a multisampled EGL image."));
3960 return false;
3961 }
3962
Jamie Madilla3944d42016-07-22 22:13:26 -04003963 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003964 if (!textureCaps.texturable)
3965 {
Jamie Madill437fa652016-05-03 15:13:24 -04003966 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003967 "EGL image internal format is not supported as a texture."));
3968 return false;
3969 }
3970
Geoff Langdcab33b2015-07-21 13:03:16 -04003971 return true;
3972}
3973
3974bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3975 egl::Display *display,
3976 GLenum target,
3977 egl::Image *image)
3978{
Geoff Langa8406172015-07-21 16:53:39 -04003979 if (!context->getExtensions().eglImage)
3980 {
Jamie Madill437fa652016-05-03 15:13:24 -04003981 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003982 return false;
3983 }
3984
3985 switch (target)
3986 {
3987 case GL_RENDERBUFFER:
3988 break;
3989
3990 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003991 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003992 return false;
3993 }
3994
3995 if (!display->isValidImage(image))
3996 {
Jamie Madill437fa652016-05-03 15:13:24 -04003997 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003998 return false;
3999 }
4000
Jamie Madilla3944d42016-07-22 22:13:26 -04004001 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04004002 if (!textureCaps.renderable)
4003 {
Jamie Madill437fa652016-05-03 15:13:24 -04004004 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04004005 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
4006 return false;
4007 }
4008
Geoff Langdcab33b2015-07-21 13:03:16 -04004009 return true;
4010}
Austin Kinrossbc781f32015-10-26 09:27:38 -07004011
4012bool ValidateBindVertexArrayBase(Context *context, GLuint array)
4013{
Geoff Lang36167ab2015-12-07 10:27:14 -05004014 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07004015 {
4016 // The default VAO should always exist
4017 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04004018 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07004019 return false;
4020 }
4021
4022 return true;
4023}
4024
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004025bool ValidateLinkProgram(Context *context, GLuint program)
4026{
4027 if (context->hasActiveTransformFeedback(program))
4028 {
4029 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004030 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004031 "Cannot link program while program is associated with an active "
4032 "transform feedback object."));
4033 return false;
4034 }
4035 return true;
4036}
4037
Geoff Langc5629752015-12-07 16:29:04 -05004038bool ValidateProgramBinaryBase(Context *context,
4039 GLuint program,
4040 GLenum binaryFormat,
4041 const void *binary,
4042 GLint length)
4043{
4044 Program *programObject = GetValidProgram(context, program);
4045 if (programObject == nullptr)
4046 {
4047 return false;
4048 }
4049
4050 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
4051 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
4052 programBinaryFormats.end())
4053 {
Jamie Madill437fa652016-05-03 15:13:24 -04004054 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05004055 return false;
4056 }
4057
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004058 if (context->hasActiveTransformFeedback(program))
4059 {
4060 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004061 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004062 "Cannot change program binary while program is associated with "
4063 "an active transform feedback object."));
4064 return false;
4065 }
4066
Geoff Langc5629752015-12-07 16:29:04 -05004067 return true;
4068}
4069
4070bool ValidateGetProgramBinaryBase(Context *context,
4071 GLuint program,
4072 GLsizei bufSize,
4073 GLsizei *length,
4074 GLenum *binaryFormat,
4075 void *binary)
4076{
4077 Program *programObject = GetValidProgram(context, program);
4078 if (programObject == nullptr)
4079 {
4080 return false;
4081 }
4082
4083 if (!programObject->isLinked())
4084 {
Jamie Madill437fa652016-05-03 15:13:24 -04004085 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004086 return false;
4087 }
4088
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004089 if (context->getCaps().programBinaryFormats.empty())
4090 {
4091 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4092 return false;
4093 }
4094
Geoff Langc5629752015-12-07 16:29:04 -05004095 return true;
4096}
Jamie Madillc29968b2016-01-20 11:17:23 -05004097
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004098bool ValidateUseProgram(Context *context, GLuint program)
4099{
4100 if (program != 0)
4101 {
4102 Program *programObject = context->getProgram(program);
4103 if (!programObject)
4104 {
4105 // ES 3.1.0 section 7.3 page 72
4106 if (context->getShader(program))
4107 {
Jamie Madill437fa652016-05-03 15:13:24 -04004108 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004109 Error(GL_INVALID_OPERATION,
4110 "Attempted to use a single shader instead of a shader program."));
4111 return false;
4112 }
4113 else
4114 {
Jamie Madill437fa652016-05-03 15:13:24 -04004115 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004116 return false;
4117 }
4118 }
4119 if (!programObject->isLinked())
4120 {
Jamie Madill437fa652016-05-03 15:13:24 -04004121 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004122 return false;
4123 }
4124 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004125 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004126 {
4127 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004128 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004129 Error(GL_INVALID_OPERATION,
4130 "Cannot change active program while transform feedback is unpaused."));
4131 return false;
4132 }
4133
4134 return true;
4135}
4136
Jamie Madillc29968b2016-01-20 11:17:23 -05004137bool ValidateCopyTexImage2D(ValidationContext *context,
4138 GLenum target,
4139 GLint level,
4140 GLenum internalformat,
4141 GLint x,
4142 GLint y,
4143 GLsizei width,
4144 GLsizei height,
4145 GLint border)
4146{
Martin Radev1be913c2016-07-11 17:59:16 +03004147 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004148 {
4149 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4150 0, x, y, width, height, border);
4151 }
4152
Martin Radev1be913c2016-07-11 17:59:16 +03004153 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004154 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4155 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004156}
Jamie Madillc29968b2016-01-20 11:17:23 -05004157
4158bool ValidateFramebufferRenderbuffer(Context *context,
4159 GLenum target,
4160 GLenum attachment,
4161 GLenum renderbuffertarget,
4162 GLuint renderbuffer)
4163{
4164 if (!ValidFramebufferTarget(target) ||
4165 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4166 {
Jamie Madill437fa652016-05-03 15:13:24 -04004167 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004168 return false;
4169 }
4170
4171 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4172 renderbuffertarget, renderbuffer);
4173}
4174
4175bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4176{
4177 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4178 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4179 {
Jamie Madill437fa652016-05-03 15:13:24 -04004180 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004181 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4182 return false;
4183 }
4184
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004185 ASSERT(context->getGLState().getDrawFramebuffer());
4186 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004187 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4188
4189 // This should come first before the check for the default frame buffer
4190 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4191 // rather than INVALID_OPERATION
4192 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4193 {
4194 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4195
4196 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004197 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4198 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004199 {
4200 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004201 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4202 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4203 // 3.1 is still a bit ambiguous about the error, but future specs are
4204 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004205 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004206 return false;
4207 }
4208 else if (bufs[colorAttachment] >= maxColorAttachment)
4209 {
Jamie Madill437fa652016-05-03 15:13:24 -04004210 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004211 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004212 return false;
4213 }
4214 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4215 frameBufferId != 0)
4216 {
4217 // INVALID_OPERATION-GL is bound to buffer and ith argument
4218 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004219 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004220 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4221 return false;
4222 }
4223 }
4224
4225 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4226 // and n is not 1 or bufs is bound to value other than BACK and NONE
4227 if (frameBufferId == 0)
4228 {
4229 if (n != 1)
4230 {
Jamie Madill437fa652016-05-03 15:13:24 -04004231 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004232 "n must be 1 when GL is bound to the default framebuffer"));
4233 return false;
4234 }
4235
4236 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4237 {
Jamie Madill437fa652016-05-03 15:13:24 -04004238 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004239 GL_INVALID_OPERATION,
4240 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4241 return false;
4242 }
4243 }
4244
4245 return true;
4246}
4247
4248bool ValidateCopyTexSubImage2D(Context *context,
4249 GLenum target,
4250 GLint level,
4251 GLint xoffset,
4252 GLint yoffset,
4253 GLint x,
4254 GLint y,
4255 GLsizei width,
4256 GLsizei height)
4257{
Martin Radev1be913c2016-07-11 17:59:16 +03004258 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004259 {
4260 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4261 yoffset, x, y, width, height, 0);
4262 }
4263
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004264 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4265 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004266}
4267
Geoff Lang496c02d2016-10-20 11:38:11 -07004268bool ValidateGetBufferPointervBase(Context *context,
4269 GLenum target,
4270 GLenum pname,
4271 GLsizei *length,
4272 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004273{
Geoff Lang496c02d2016-10-20 11:38:11 -07004274 if (length)
4275 {
4276 *length = 0;
4277 }
4278
4279 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4280 {
4281 context->handleError(
4282 Error(GL_INVALID_OPERATION,
4283 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
4284 return false;
4285 }
4286
Olli Etuaho4f667482016-03-30 15:56:35 +03004287 if (!ValidBufferTarget(context, target))
4288 {
Jamie Madill437fa652016-05-03 15:13:24 -04004289 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004290 return false;
4291 }
4292
Geoff Lang496c02d2016-10-20 11:38:11 -07004293 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004294 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004295 case GL_BUFFER_MAP_POINTER:
4296 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004297
Geoff Lang496c02d2016-10-20 11:38:11 -07004298 default:
4299 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4300 return false;
4301 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004302
4303 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4304 // target bound to zero generate an INVALID_OPERATION error."
4305 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004306 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004307 {
Jamie Madill437fa652016-05-03 15:13:24 -04004308 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004309 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4310 return false;
4311 }
4312
Geoff Lang496c02d2016-10-20 11:38:11 -07004313 if (length)
4314 {
4315 *length = 1;
4316 }
4317
Olli Etuaho4f667482016-03-30 15:56:35 +03004318 return true;
4319}
4320
4321bool ValidateUnmapBufferBase(Context *context, GLenum target)
4322{
4323 if (!ValidBufferTarget(context, target))
4324 {
Jamie Madill437fa652016-05-03 15:13:24 -04004325 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004326 return false;
4327 }
4328
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004329 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004330
4331 if (buffer == nullptr || !buffer->isMapped())
4332 {
Jamie Madill437fa652016-05-03 15:13:24 -04004333 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004334 return false;
4335 }
4336
4337 return true;
4338}
4339
4340bool ValidateMapBufferRangeBase(Context *context,
4341 GLenum target,
4342 GLintptr offset,
4343 GLsizeiptr length,
4344 GLbitfield access)
4345{
4346 if (!ValidBufferTarget(context, target))
4347 {
Jamie Madill437fa652016-05-03 15:13:24 -04004348 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004349 return false;
4350 }
4351
4352 if (offset < 0 || length < 0)
4353 {
Jamie Madill437fa652016-05-03 15:13:24 -04004354 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004355 return false;
4356 }
4357
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004358 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004359
4360 if (!buffer)
4361 {
Jamie Madill437fa652016-05-03 15:13:24 -04004362 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004363 return false;
4364 }
4365
4366 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004367 CheckedNumeric<size_t> checkedOffset(offset);
4368 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004369
Jamie Madille2e406c2016-06-02 13:04:10 -04004370 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004371 {
Jamie Madill437fa652016-05-03 15:13:24 -04004372 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004373 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4374 return false;
4375 }
4376
4377 // Check for invalid bits in the mask
4378 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4379 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4380 GL_MAP_UNSYNCHRONIZED_BIT;
4381
4382 if (access & ~(allAccessBits))
4383 {
Jamie Madill437fa652016-05-03 15:13:24 -04004384 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004385 return false;
4386 }
4387
4388 if (length == 0)
4389 {
Jamie Madill437fa652016-05-03 15:13:24 -04004390 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004391 return false;
4392 }
4393
4394 if (buffer->isMapped())
4395 {
Jamie Madill437fa652016-05-03 15:13:24 -04004396 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004397 return false;
4398 }
4399
4400 // Check for invalid bit combinations
4401 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4402 {
Jamie Madill437fa652016-05-03 15:13:24 -04004403 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004404 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4405 return false;
4406 }
4407
4408 GLbitfield writeOnlyBits =
4409 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4410
4411 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4412 {
Jamie Madill437fa652016-05-03 15:13:24 -04004413 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004414 "Invalid access bits when mapping buffer for reading: 0x%X.",
4415 access));
4416 return false;
4417 }
4418
4419 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4420 {
Jamie Madill437fa652016-05-03 15:13:24 -04004421 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004422 GL_INVALID_OPERATION,
4423 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4424 return false;
4425 }
4426 return true;
4427}
4428
4429bool ValidateFlushMappedBufferRangeBase(Context *context,
4430 GLenum target,
4431 GLintptr offset,
4432 GLsizeiptr length)
4433{
4434 if (offset < 0 || length < 0)
4435 {
Jamie Madill437fa652016-05-03 15:13:24 -04004436 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004437 return false;
4438 }
4439
4440 if (!ValidBufferTarget(context, target))
4441 {
Jamie Madill437fa652016-05-03 15:13:24 -04004442 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004443 return false;
4444 }
4445
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004446 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004447
4448 if (buffer == nullptr)
4449 {
Jamie Madill437fa652016-05-03 15:13:24 -04004450 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004451 return false;
4452 }
4453
4454 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4455 {
Jamie Madill437fa652016-05-03 15:13:24 -04004456 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004457 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4458 return false;
4459 }
4460
4461 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004462 CheckedNumeric<size_t> checkedOffset(offset);
4463 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004464
Jamie Madille2e406c2016-06-02 13:04:10 -04004465 if (!checkedSize.IsValid() ||
4466 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004467 {
Jamie Madill437fa652016-05-03 15:13:24 -04004468 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004469 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4470 return false;
4471 }
4472
4473 return true;
4474}
4475
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004476bool ValidateGenerateMipmap(Context *context, GLenum target)
4477{
4478 if (!ValidTextureTarget(context, target))
4479 {
4480 context->handleError(Error(GL_INVALID_ENUM));
4481 return false;
4482 }
4483
4484 Texture *texture = context->getTargetTexture(target);
4485
4486 if (texture == nullptr)
4487 {
4488 context->handleError(Error(GL_INVALID_OPERATION));
4489 return false;
4490 }
4491
4492 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4493
4494 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4495 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4496 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4497 {
4498 context->handleError(Error(GL_INVALID_OPERATION));
4499 return false;
4500 }
4501
Jamie Madilla3944d42016-07-22 22:13:26 -04004502 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4503 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4504 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004505
4506 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4507 // unsized formats or that are color renderable and filterable. Since we do not track if
4508 // the texture was created with sized or unsized format (only sized formats are stored),
4509 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4510 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4511 // textures since they're the only texture format that can be created with unsized formats
4512 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4513 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004514 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4515 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004516 {
4517 context->handleError(Error(GL_INVALID_OPERATION));
4518 return false;
4519 }
4520
4521 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004522 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004523 {
4524 context->handleError(Error(GL_INVALID_OPERATION));
4525 return false;
4526 }
4527
4528 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004529 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004530 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4531 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4532 {
Geoff Lang55482a12016-11-21 16:54:01 -05004533 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004534 context->handleError(Error(GL_INVALID_OPERATION));
4535 return false;
4536 }
4537
4538 // Cube completeness check
4539 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4540 {
4541 context->handleError(Error(GL_INVALID_OPERATION));
4542 return false;
4543 }
4544
4545 return true;
4546}
4547
Olli Etuaho41997e72016-03-10 13:38:39 +02004548bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4549{
4550 return ValidateGenOrDelete(context, n);
4551}
4552
4553bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4554{
4555 return ValidateGenOrDelete(context, n);
4556}
4557
4558bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4559{
4560 return ValidateGenOrDelete(context, n);
4561}
4562
4563bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4564{
4565 return ValidateGenOrDelete(context, n);
4566}
4567
4568bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4569{
4570 return ValidateGenOrDelete(context, n);
4571}
4572
4573bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4574{
4575 return ValidateGenOrDelete(context, n);
4576}
4577
4578bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4579{
4580 return ValidateGenOrDelete(context, n);
4581}
4582
4583bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4584{
4585 return ValidateGenOrDelete(context, n);
4586}
4587
4588bool ValidateGenOrDelete(Context *context, GLint n)
4589{
4590 if (n < 0)
4591 {
Jamie Madill437fa652016-05-03 15:13:24 -04004592 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004593 return false;
4594 }
4595 return true;
4596}
4597
Geoff Langf41a7152016-09-19 15:11:17 -04004598bool ValidateEnable(Context *context, GLenum cap)
4599{
4600 if (!ValidCap(context, cap, false))
4601 {
4602 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4603 return false;
4604 }
4605
4606 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4607 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4608 {
4609 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4610 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4611
4612 // We also output an error message to the debugger window if tracing is active, so that
4613 // developers can see the error message.
Jamie Madill6a6b09c2017-01-12 21:52:29 +00004614 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004615 return false;
4616 }
4617
4618 return true;
4619}
4620
4621bool ValidateDisable(Context *context, GLenum cap)
4622{
4623 if (!ValidCap(context, cap, false))
4624 {
4625 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4626 return false;
4627 }
4628
4629 return true;
4630}
4631
4632bool ValidateIsEnabled(Context *context, GLenum cap)
4633{
4634 if (!ValidCap(context, cap, true))
4635 {
4636 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4637 return false;
4638 }
4639
4640 return true;
4641}
4642
Geoff Langff5b2d52016-09-07 11:32:23 -04004643bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4644{
4645 if (!context->getExtensions().robustClientMemory)
4646 {
4647 context->handleError(
4648 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4649 return false;
4650 }
4651
4652 if (bufSize < 0)
4653 {
4654 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4655 return false;
4656 }
4657
4658 return true;
4659}
4660
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004661bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4662{
4663 if (bufSize < numParams)
4664 {
4665 context->handleError(Error(GL_INVALID_OPERATION,
4666 "%u parameters are required but %i were provided.", numParams,
4667 bufSize));
4668 return false;
4669 }
4670
4671 return true;
4672}
4673
Geoff Langff5b2d52016-09-07 11:32:23 -04004674bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4675 GLenum target,
4676 GLenum attachment,
4677 GLenum pname,
4678 GLsizei *numParams)
4679{
4680 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4681 *numParams = 1;
4682
4683 if (!ValidFramebufferTarget(target))
4684 {
4685 context->handleError(Error(GL_INVALID_ENUM));
4686 return false;
4687 }
4688
4689 int clientVersion = context->getClientMajorVersion();
4690
4691 switch (pname)
4692 {
4693 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4694 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4695 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4696 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4697 break;
4698
4699 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4700 if (clientVersion < 3 && !context->getExtensions().sRGB)
4701 {
4702 context->handleError(Error(GL_INVALID_ENUM));
4703 return false;
4704 }
4705 break;
4706
4707 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4708 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4709 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4710 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4711 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4712 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4713 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4714 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4715 if (clientVersion < 3)
4716 {
4717 context->handleError(Error(GL_INVALID_ENUM));
4718 return false;
4719 }
4720 break;
4721
4722 default:
4723 context->handleError(Error(GL_INVALID_ENUM));
4724 return false;
4725 }
4726
4727 // Determine if the attachment is a valid enum
4728 switch (attachment)
4729 {
4730 case GL_BACK:
4731 case GL_FRONT:
4732 case GL_DEPTH:
4733 case GL_STENCIL:
4734 case GL_DEPTH_STENCIL_ATTACHMENT:
4735 if (clientVersion < 3)
4736 {
4737 context->handleError(Error(GL_INVALID_ENUM));
4738 return false;
4739 }
4740 break;
4741
4742 case GL_DEPTH_ATTACHMENT:
4743 case GL_STENCIL_ATTACHMENT:
4744 break;
4745
4746 default:
4747 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4748 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4749 {
4750 context->handleError(Error(GL_INVALID_ENUM));
4751 return false;
4752 }
4753 break;
4754 }
4755
4756 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4757 ASSERT(framebuffer);
4758
4759 if (framebuffer->id() == 0)
4760 {
4761 if (clientVersion < 3)
4762 {
4763 context->handleError(Error(GL_INVALID_OPERATION));
4764 return false;
4765 }
4766
4767 switch (attachment)
4768 {
4769 case GL_BACK:
4770 case GL_DEPTH:
4771 case GL_STENCIL:
4772 break;
4773
4774 default:
4775 context->handleError(Error(GL_INVALID_OPERATION));
4776 return false;
4777 }
4778 }
4779 else
4780 {
4781 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4782 {
4783 // Valid attachment query
4784 }
4785 else
4786 {
4787 switch (attachment)
4788 {
4789 case GL_DEPTH_ATTACHMENT:
4790 case GL_STENCIL_ATTACHMENT:
4791 break;
4792
4793 case GL_DEPTH_STENCIL_ATTACHMENT:
4794 if (!framebuffer->hasValidDepthStencil())
4795 {
4796 context->handleError(Error(GL_INVALID_OPERATION));
4797 return false;
4798 }
4799 break;
4800
4801 default:
4802 context->handleError(Error(GL_INVALID_OPERATION));
4803 return false;
4804 }
4805 }
4806 }
4807
4808 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4809 if (attachmentObject)
4810 {
4811 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4812 attachmentObject->type() == GL_TEXTURE ||
4813 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4814
4815 switch (pname)
4816 {
4817 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4818 if (attachmentObject->type() != GL_RENDERBUFFER &&
4819 attachmentObject->type() != GL_TEXTURE)
4820 {
4821 context->handleError(Error(GL_INVALID_ENUM));
4822 return false;
4823 }
4824 break;
4825
4826 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4827 if (attachmentObject->type() != GL_TEXTURE)
4828 {
4829 context->handleError(Error(GL_INVALID_ENUM));
4830 return false;
4831 }
4832 break;
4833
4834 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4835 if (attachmentObject->type() != GL_TEXTURE)
4836 {
4837 context->handleError(Error(GL_INVALID_ENUM));
4838 return false;
4839 }
4840 break;
4841
4842 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4843 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4844 {
4845 context->handleError(Error(GL_INVALID_OPERATION));
4846 return false;
4847 }
4848 break;
4849
4850 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4851 if (attachmentObject->type() != GL_TEXTURE)
4852 {
4853 context->handleError(Error(GL_INVALID_ENUM));
4854 return false;
4855 }
4856 break;
4857
4858 default:
4859 break;
4860 }
4861 }
4862 else
4863 {
4864 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4865 // is NONE, then querying any other pname will generate INVALID_ENUM.
4866
4867 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4868 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4869 // INVALID_OPERATION for all other pnames
4870
4871 switch (pname)
4872 {
4873 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4874 break;
4875
4876 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4877 if (clientVersion < 3)
4878 {
4879 context->handleError(Error(GL_INVALID_ENUM));
4880 return false;
4881 }
4882 break;
4883
4884 default:
4885 if (clientVersion < 3)
4886 {
4887 context->handleError(Error(GL_INVALID_ENUM));
4888 return false;
4889 }
4890 else
4891 {
4892 context->handleError(Error(GL_INVALID_OPERATION));
4893 return false;
4894 }
4895 }
4896 }
4897
4898 return true;
4899}
4900
4901bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4902 GLenum target,
4903 GLenum attachment,
4904 GLenum pname,
4905 GLsizei bufSize,
4906 GLsizei *numParams)
4907{
4908 if (!ValidateRobustEntryPoint(context, bufSize))
4909 {
4910 return false;
4911 }
4912
4913 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4914 {
4915 return false;
4916 }
4917
4918 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4919 {
4920 return false;
4921 }
4922
4923 return true;
4924}
4925
4926bool ValidateGetBufferParameteriv(ValidationContext *context,
4927 GLenum target,
4928 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004929 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004930{
Geoff Langebebe1c2016-10-14 12:01:31 -04004931 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004932}
4933
4934bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4935 GLenum target,
4936 GLenum pname,
4937 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004938 GLsizei *length,
4939 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004940{
4941 if (!ValidateRobustEntryPoint(context, bufSize))
4942 {
4943 return false;
4944 }
4945
Geoff Langebebe1c2016-10-14 12:01:31 -04004946 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004947 {
4948 return false;
4949 }
4950
Geoff Langebebe1c2016-10-14 12:01:31 -04004951 if (!ValidateRobustBufferSize(context, bufSize, *length))
4952 {
4953 return false;
4954 }
4955
4956 return true;
4957}
4958
4959bool ValidateGetBufferParameteri64v(ValidationContext *context,
4960 GLenum target,
4961 GLenum pname,
4962 GLint64 *params)
4963{
4964 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4965}
4966
4967bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4968 GLenum target,
4969 GLenum pname,
4970 GLsizei bufSize,
4971 GLsizei *length,
4972 GLint64 *params)
4973{
4974 if (!ValidateRobustEntryPoint(context, bufSize))
4975 {
4976 return false;
4977 }
4978
4979 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4980 {
4981 return false;
4982 }
4983
4984 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004985 {
4986 return false;
4987 }
4988
4989 return true;
4990}
4991
4992bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4993{
4994 // Currently, all GetProgramiv queries return 1 parameter
4995 *numParams = 1;
4996
4997 Program *programObject = GetValidProgram(context, program);
4998 if (!programObject)
4999 {
5000 return false;
5001 }
5002
5003 switch (pname)
5004 {
5005 case GL_DELETE_STATUS:
5006 case GL_LINK_STATUS:
5007 case GL_VALIDATE_STATUS:
5008 case GL_INFO_LOG_LENGTH:
5009 case GL_ATTACHED_SHADERS:
5010 case GL_ACTIVE_ATTRIBUTES:
5011 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
5012 case GL_ACTIVE_UNIFORMS:
5013 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
5014 break;
5015
5016 case GL_PROGRAM_BINARY_LENGTH:
5017 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
5018 {
5019 context->handleError(Error(GL_INVALID_ENUM,
5020 "Querying GL_PROGRAM_BINARY_LENGTH requires "
5021 "GL_OES_get_program_binary or ES 3.0."));
5022 return false;
5023 }
5024 break;
5025
5026 case GL_ACTIVE_UNIFORM_BLOCKS:
5027 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
5028 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
5029 case GL_TRANSFORM_FEEDBACK_VARYINGS:
5030 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
5031 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
5032 if (context->getClientMajorVersion() < 3)
5033 {
5034 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
5035 return false;
5036 }
5037 break;
5038
5039 default:
5040 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
5041 return false;
5042 }
5043
5044 return true;
5045}
5046
5047bool ValidateGetProgramivRobustANGLE(Context *context,
5048 GLuint program,
5049 GLenum pname,
5050 GLsizei bufSize,
5051 GLsizei *numParams)
5052{
5053 if (!ValidateRobustEntryPoint(context, bufSize))
5054 {
5055 return false;
5056 }
5057
5058 if (!ValidateGetProgramiv(context, program, pname, numParams))
5059 {
5060 return false;
5061 }
5062
5063 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5064 {
5065 return false;
5066 }
5067
5068 return true;
5069}
5070
Geoff Lang740d9022016-10-07 11:20:52 -04005071bool ValidateGetRenderbufferParameteriv(Context *context,
5072 GLenum target,
5073 GLenum pname,
5074 GLint *params)
5075{
5076 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5077}
5078
5079bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5080 GLenum target,
5081 GLenum pname,
5082 GLsizei bufSize,
5083 GLsizei *length,
5084 GLint *params)
5085{
5086 if (!ValidateRobustEntryPoint(context, bufSize))
5087 {
5088 return false;
5089 }
5090
5091 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5092 {
5093 return false;
5094 }
5095
5096 if (!ValidateRobustBufferSize(context, bufSize, *length))
5097 {
5098 return false;
5099 }
5100
5101 return true;
5102}
5103
Geoff Langd7d0ed32016-10-07 11:33:51 -04005104bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5105{
5106 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5107}
5108
5109bool ValidateGetShaderivRobustANGLE(Context *context,
5110 GLuint shader,
5111 GLenum pname,
5112 GLsizei bufSize,
5113 GLsizei *length,
5114 GLint *params)
5115{
5116 if (!ValidateRobustEntryPoint(context, bufSize))
5117 {
5118 return false;
5119 }
5120
5121 if (!ValidateGetShaderivBase(context, shader, pname, length))
5122 {
5123 return false;
5124 }
5125
5126 if (!ValidateRobustBufferSize(context, bufSize, *length))
5127 {
5128 return false;
5129 }
5130
5131 return true;
5132}
5133
Geoff Langc1984ed2016-10-07 12:41:00 -04005134bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5135{
5136 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5137}
5138
5139bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5140 GLenum target,
5141 GLenum pname,
5142 GLsizei bufSize,
5143 GLsizei *length,
5144 GLfloat *params)
5145{
5146 if (!ValidateRobustEntryPoint(context, bufSize))
5147 {
5148 return false;
5149 }
5150
5151 if (!ValidateGetTexParameterBase(context, target, pname, length))
5152 {
5153 return false;
5154 }
5155
5156 if (!ValidateRobustBufferSize(context, bufSize, *length))
5157 {
5158 return false;
5159 }
5160
5161 return true;
5162}
5163
5164bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5165{
5166 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5167}
5168
5169bool ValidateGetTexParameterivRobustANGLE(Context *context,
5170 GLenum target,
5171 GLenum pname,
5172 GLsizei bufSize,
5173 GLsizei *length,
5174 GLint *params)
5175{
5176 if (!ValidateRobustEntryPoint(context, bufSize))
5177 {
5178 return false;
5179 }
5180
5181 if (!ValidateGetTexParameterBase(context, target, pname, length))
5182 {
5183 return false;
5184 }
5185
5186 if (!ValidateRobustBufferSize(context, bufSize, *length))
5187 {
5188 return false;
5189 }
5190
5191 return true;
5192}
5193
5194bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5195{
5196 return ValidateTexParameterBase(context, target, pname, -1, &param);
5197}
5198
5199bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5200{
5201 return ValidateTexParameterBase(context, target, pname, -1, params);
5202}
5203
5204bool ValidateTexParameterfvRobustANGLE(Context *context,
5205 GLenum target,
5206 GLenum pname,
5207 GLsizei bufSize,
5208 const GLfloat *params)
5209{
5210 if (!ValidateRobustEntryPoint(context, bufSize))
5211 {
5212 return false;
5213 }
5214
5215 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5216}
5217
5218bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5219{
5220 return ValidateTexParameterBase(context, target, pname, -1, &param);
5221}
5222
5223bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5224{
5225 return ValidateTexParameterBase(context, target, pname, -1, params);
5226}
5227
5228bool ValidateTexParameterivRobustANGLE(Context *context,
5229 GLenum target,
5230 GLenum pname,
5231 GLsizei bufSize,
5232 const GLint *params)
5233{
5234 if (!ValidateRobustEntryPoint(context, bufSize))
5235 {
5236 return false;
5237 }
5238
5239 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5240}
5241
5242bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5243{
5244 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5245}
5246
5247bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5248 GLuint sampler,
5249 GLenum pname,
5250 GLuint bufSize,
5251 GLsizei *length,
5252 GLfloat *params)
5253{
5254 if (!ValidateRobustEntryPoint(context, bufSize))
5255 {
5256 return false;
5257 }
5258
5259 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5260 {
5261 return false;
5262 }
5263
5264 if (!ValidateRobustBufferSize(context, bufSize, *length))
5265 {
5266 return false;
5267 }
5268
5269 return true;
5270}
5271
5272bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5273{
5274 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5275}
5276
5277bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5278 GLuint sampler,
5279 GLenum pname,
5280 GLuint bufSize,
5281 GLsizei *length,
5282 GLint *params)
5283{
5284 if (!ValidateRobustEntryPoint(context, bufSize))
5285 {
5286 return false;
5287 }
5288
5289 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5290 {
5291 return false;
5292 }
5293
5294 if (!ValidateRobustBufferSize(context, bufSize, *length))
5295 {
5296 return false;
5297 }
5298
5299 return true;
5300}
5301
5302bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5303{
5304 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5305}
5306
5307bool ValidateSamplerParameterfv(Context *context,
5308 GLuint sampler,
5309 GLenum pname,
5310 const GLfloat *params)
5311{
5312 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5313}
5314
5315bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5316 GLuint sampler,
5317 GLenum pname,
5318 GLsizei bufSize,
5319 const GLfloat *params)
5320{
5321 if (!ValidateRobustEntryPoint(context, bufSize))
5322 {
5323 return false;
5324 }
5325
5326 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5327}
5328
5329bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5330{
5331 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5332}
5333
5334bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5335{
5336 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5337}
5338
5339bool ValidateSamplerParameterivRobustANGLE(Context *context,
5340 GLuint sampler,
5341 GLenum pname,
5342 GLsizei bufSize,
5343 const GLint *params)
5344{
5345 if (!ValidateRobustEntryPoint(context, bufSize))
5346 {
5347 return false;
5348 }
5349
5350 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5351}
5352
Geoff Lang0b031062016-10-13 14:30:04 -04005353bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5354{
5355 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5356}
5357
5358bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5359 GLuint index,
5360 GLenum pname,
5361 GLsizei bufSize,
5362 GLsizei *length,
5363 GLfloat *params)
5364{
5365 if (!ValidateRobustEntryPoint(context, bufSize))
5366 {
5367 return false;
5368 }
5369
5370 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5371 {
5372 return false;
5373 }
5374
5375 if (!ValidateRobustBufferSize(context, bufSize, *length))
5376 {
5377 return false;
5378 }
5379
5380 return true;
5381}
5382
5383bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5384{
5385 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5386}
5387
5388bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5389 GLuint index,
5390 GLenum pname,
5391 GLsizei bufSize,
5392 GLsizei *length,
5393 GLint *params)
5394{
5395 if (!ValidateRobustEntryPoint(context, bufSize))
5396 {
5397 return false;
5398 }
5399
5400 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5401 {
5402 return false;
5403 }
5404
5405 if (!ValidateRobustBufferSize(context, bufSize, *length))
5406 {
5407 return false;
5408 }
5409
5410 return true;
5411}
5412
5413bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5414{
5415 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5416}
5417
5418bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5419 GLuint index,
5420 GLenum pname,
5421 GLsizei bufSize,
5422 GLsizei *length,
5423 void **pointer)
5424{
5425 if (!ValidateRobustEntryPoint(context, bufSize))
5426 {
5427 return false;
5428 }
5429
5430 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5431 {
5432 return false;
5433 }
5434
5435 if (!ValidateRobustBufferSize(context, bufSize, *length))
5436 {
5437 return false;
5438 }
5439
5440 return true;
5441}
5442
5443bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5444{
5445 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5446}
5447
5448bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5449 GLuint index,
5450 GLenum pname,
5451 GLsizei bufSize,
5452 GLsizei *length,
5453 GLint *params)
5454{
5455 if (!ValidateRobustEntryPoint(context, bufSize))
5456 {
5457 return false;
5458 }
5459
5460 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5461 {
5462 return false;
5463 }
5464
5465 if (!ValidateRobustBufferSize(context, bufSize, *length))
5466 {
5467 return false;
5468 }
5469
5470 return true;
5471}
5472
5473bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5474{
5475 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5476}
5477
5478bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5479 GLuint index,
5480 GLenum pname,
5481 GLsizei bufSize,
5482 GLsizei *length,
5483 GLuint *params)
5484{
5485 if (!ValidateRobustEntryPoint(context, bufSize))
5486 {
5487 return false;
5488 }
5489
5490 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5491 {
5492 return false;
5493 }
5494
5495 if (!ValidateRobustBufferSize(context, bufSize, *length))
5496 {
5497 return false;
5498 }
5499
5500 return true;
5501}
5502
Geoff Lang6899b872016-10-14 11:30:13 -04005503bool ValidateGetActiveUniformBlockiv(Context *context,
5504 GLuint program,
5505 GLuint uniformBlockIndex,
5506 GLenum pname,
5507 GLint *params)
5508{
5509 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5510}
5511
5512bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5513 GLuint program,
5514 GLuint uniformBlockIndex,
5515 GLenum pname,
5516 GLsizei bufSize,
5517 GLsizei *length,
5518 GLint *params)
5519{
5520 if (!ValidateRobustEntryPoint(context, bufSize))
5521 {
5522 return false;
5523 }
5524
5525 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5526 {
5527 return false;
5528 }
5529
5530 if (!ValidateRobustBufferSize(context, bufSize, *length))
5531 {
5532 return false;
5533 }
5534
5535 return true;
5536}
5537
Geoff Lang0a9661f2016-10-20 10:59:20 -07005538bool ValidateGetInternalFormativ(Context *context,
5539 GLenum target,
5540 GLenum internalformat,
5541 GLenum pname,
5542 GLsizei bufSize,
5543 GLint *params)
5544{
5545 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5546 nullptr);
5547}
5548
5549bool ValidateGetInternalFormativRobustANGLE(Context *context,
5550 GLenum target,
5551 GLenum internalformat,
5552 GLenum pname,
5553 GLsizei bufSize,
5554 GLsizei *length,
5555 GLint *params)
5556{
5557 if (!ValidateRobustEntryPoint(context, bufSize))
5558 {
5559 return false;
5560 }
5561
5562 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5563 {
5564 return false;
5565 }
5566
5567 if (!ValidateRobustBufferSize(context, bufSize, *length))
5568 {
5569 return false;
5570 }
5571
5572 return true;
5573}
5574
Jamie Madillc29968b2016-01-20 11:17:23 -05005575} // namespace gl