blob: fb1fc423ef5214d334eb17bbb897d2b75f7c082e [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];
Jamie Madill63805b42015-08-25 13:17:39 -040053 if (program->isAttribLocationActive(attributeIndex) && attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040054 {
55 gl::Buffer *buffer = attrib.buffer.get();
56
57 if (buffer)
58 {
Corentin Wallez92db6942016-12-09 13:10:36 -050059 CheckedNumeric<GLint64> maxVertexElement = 0;
60 bool readsData = false;
61 if (attrib.divisor == 0)
Jamie Madill1ca74672015-07-21 15:14:11 -040062 {
Corentin Wallez92db6942016-12-09 13:10:36 -050063 readsData = vertexCount > 0;
Jamie Madill1ca74672015-07-21 15:14:11 -040064 maxVertexElement = static_cast<GLint64>(maxVertex);
65 }
Corentin Wallez92db6942016-12-09 13:10:36 -050066 else if (primcount > 0)
67 {
68 readsData = true;
69 maxVertexElement =
70 static_cast<GLint64>(primcount - 1) / static_cast<GLint64>(attrib.divisor);
71 }
Jamie Madill1ca74672015-07-21 15:14:11 -040072
73 // If we're drawing zero vertices, we have enough data.
Corentin Wallez92db6942016-12-09 13:10:36 -050074 if (readsData)
Jamie Madill1ca74672015-07-21 15:14:11 -040075 {
76 // Note: Last vertex element does not take the full stride!
Corentin Wallez92db6942016-12-09 13:10:36 -050077 CheckedNumeric<GLint64> attribStride = ComputeVertexAttributeStride(attrib);
78 CheckedNumeric<GLint64> attribSize = ComputeVertexAttributeTypeSize(attrib);
79 CheckedNumeric<GLint64> attribDataSize =
80 maxVertexElement * attribStride + attribSize;
81 CheckedNumeric<GLint64> maxOffset = attribDataSize + attrib.offset;
82
83 if (!maxOffset.IsValid())
84 {
85 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
86 return false;
87 }
Jamie Madill1ca74672015-07-21 15:14:11 -040088
89 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
90 // We can return INVALID_OPERATION if our vertex attribute does not have
91 // enough backing data.
Corentin Wallez92db6942016-12-09 13:10:36 -050092 if (maxOffset.ValueOrDie() > buffer->getSize())
Jamie Madill1ca74672015-07-21 15:14:11 -040093 {
Jamie Madill437fa652016-05-03 15:13:24 -040094 context->handleError(
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040095 Error(GL_INVALID_OPERATION,
96 "Vertex buffer is not big enough for the draw call"));
Jamie Madill1ca74672015-07-21 15:14:11 -040097 return false;
98 }
99 }
100 }
Corentin Wallez327411e2016-12-09 11:09:17 -0500101 else if (webglCompatibility)
102 {
103 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
104 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
105 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then
106 // calls to drawArrays or drawElements will generate an INVALID_OPERATION error.
107 context->handleError(
108 Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer."));
109 }
Jamie Madill1ca74672015-07-21 15:14:11 -0400110 else if (attrib.pointer == NULL)
111 {
112 // This is an application error that would normally result in a crash,
113 // but we catch it and return an error
Jamie Madill437fa652016-05-03 15:13:24 -0400114 context->handleError(Error(
Jamie Madill1ca74672015-07-21 15:14:11 -0400115 GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
116 return false;
117 }
118 }
119 }
120
121 return true;
122}
123
Geoff Langf607c602016-09-21 11:46:48 -0400124bool ValidReadPixelsFormatType(ValidationContext *context,
125 GLenum framebufferComponentType,
126 GLenum format,
127 GLenum type)
128{
129 switch (framebufferComponentType)
130 {
131 case GL_UNSIGNED_NORMALIZED:
132 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
133 // ReadPixels with BGRA even if the extension is not present
134 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
135 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
136 type == GL_UNSIGNED_BYTE);
137
138 case GL_SIGNED_NORMALIZED:
139 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
140
141 case GL_INT:
142 return (format == GL_RGBA_INTEGER && type == GL_INT);
143
144 case GL_UNSIGNED_INT:
145 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
146
147 case GL_FLOAT:
148 return (format == GL_RGBA && type == GL_FLOAT);
149
150 default:
151 UNREACHABLE();
152 return false;
153 }
154}
155
Geoff Langf41a7152016-09-19 15:11:17 -0400156bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500157{
158 switch (cap)
159 {
Geoff Langf41a7152016-09-19 15:11:17 -0400160 // EXT_multisample_compatibility
161 case GL_MULTISAMPLE_EXT:
162 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
163 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300164
Geoff Langf41a7152016-09-19 15:11:17 -0400165 case GL_CULL_FACE:
166 case GL_POLYGON_OFFSET_FILL:
167 case GL_SAMPLE_ALPHA_TO_COVERAGE:
168 case GL_SAMPLE_COVERAGE:
169 case GL_SCISSOR_TEST:
170 case GL_STENCIL_TEST:
171 case GL_DEPTH_TEST:
172 case GL_BLEND:
173 case GL_DITHER:
174 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500175
Geoff Langf41a7152016-09-19 15:11:17 -0400176 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
177 case GL_RASTERIZER_DISCARD:
178 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500179
Geoff Langf41a7152016-09-19 15:11:17 -0400180 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
181 case GL_DEBUG_OUTPUT:
182 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500183
Geoff Langf41a7152016-09-19 15:11:17 -0400184 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
185 return queryOnly && context->getExtensions().bindGeneratesResource;
186
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700187 case GL_FRAMEBUFFER_SRGB_EXT:
188 return context->getExtensions().sRGBWriteControl;
189
Geoff Lang3b573612016-10-31 14:08:10 -0400190 case GL_SAMPLE_MASK:
Geoff Lang3b573612016-10-31 14:08:10 -0400191 return context->getClientVersion() >= Version(3, 1);
192
Geoff Langf41a7152016-09-19 15:11:17 -0400193 default:
194 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500195 }
196}
197
Geoff Lang62fce5b2016-09-30 10:46:35 -0400198bool ValidateReadPixelsBase(ValidationContext *context,
199 GLint x,
200 GLint y,
201 GLsizei width,
202 GLsizei height,
203 GLenum format,
204 GLenum type,
205 GLsizei bufSize,
206 GLsizei *length,
207 GLvoid *pixels)
208{
209 if (length != nullptr)
210 {
211 *length = 0;
212 }
213
214 if (width < 0 || height < 0)
215 {
216 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
217 return false;
218 }
219
220 auto readFramebuffer = context->getGLState().getReadFramebuffer();
221
222 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
223 {
224 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
225 return false;
226 }
227
228 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
229 {
230 context->handleError(Error(GL_INVALID_OPERATION));
231 return false;
232 }
233
234 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
235 ASSERT(framebuffer);
236
237 if (framebuffer->getReadBufferState() == GL_NONE)
238 {
239 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
240 return false;
241 }
242
243 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500244 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
245 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
246 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
247 // situation is an application error that would lead to a crash in ANGLE.
248 if (readBuffer == nullptr)
Geoff Lang62fce5b2016-09-30 10:46:35 -0400249 {
Corentin Wallez3c90ed62016-12-16 16:19:28 -0500250 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
Geoff Lang62fce5b2016-09-30 10:46:35 -0400251 return false;
252 }
253
254 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
255 GLenum currentType = framebuffer->getImplementationColorReadType();
256 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
257
258 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
259 bool validFormatTypeCombination =
260 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
261
262 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
263 {
264 context->handleError(Error(GL_INVALID_OPERATION));
265 return false;
266 }
267
268 // Check for pixel pack buffer related API errors
269 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
270 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
271 {
272 // ...the buffer object's data store is currently mapped.
273 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
274 return false;
275 }
276
277 // .. the data would be packed to the buffer object such that the memory writes required
278 // would exceed the data store size.
279 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
280 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
281 const gl::Extents size(width, height, 1);
282 const auto &pack = context->getGLState().getPackState();
283
284 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
285 if (endByteOrErr.isError())
286 {
287 context->handleError(endByteOrErr.getError());
288 return false;
289 }
290
291 size_t endByte = endByteOrErr.getResult();
292 if (bufSize >= 0)
293 {
294
295 if (static_cast<size_t>(bufSize) < endByte)
296 {
297 context->handleError(
298 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
299 return false;
300 }
301 }
302
303 if (pixelPackBuffer != nullptr)
304 {
305 CheckedNumeric<size_t> checkedEndByte(endByte);
306 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
307 checkedEndByte += checkedOffset;
308
309 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
310 {
311 // Overflow past the end of the buffer
312 context->handleError(
313 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
314 return false;
315 }
316 }
317
318 if (length != nullptr)
319 {
320 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
321 {
322 context->handleError(
323 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
324 return false;
325 }
326
327 *length = static_cast<GLsizei>(endByte);
328 }
329
330 return true;
331}
332
Geoff Lang740d9022016-10-07 11:20:52 -0400333bool ValidateGetRenderbufferParameterivBase(Context *context,
334 GLenum target,
335 GLenum pname,
336 GLsizei *length)
337{
338 if (length)
339 {
340 *length = 0;
341 }
342
343 if (target != GL_RENDERBUFFER)
344 {
345 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
346 return false;
347 }
348
349 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
350 if (renderbuffer == nullptr)
351 {
352 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
353 return false;
354 }
355
356 switch (pname)
357 {
358 case GL_RENDERBUFFER_WIDTH:
359 case GL_RENDERBUFFER_HEIGHT:
360 case GL_RENDERBUFFER_INTERNAL_FORMAT:
361 case GL_RENDERBUFFER_RED_SIZE:
362 case GL_RENDERBUFFER_GREEN_SIZE:
363 case GL_RENDERBUFFER_BLUE_SIZE:
364 case GL_RENDERBUFFER_ALPHA_SIZE:
365 case GL_RENDERBUFFER_DEPTH_SIZE:
366 case GL_RENDERBUFFER_STENCIL_SIZE:
367 break;
368
369 case GL_RENDERBUFFER_SAMPLES_ANGLE:
370 if (!context->getExtensions().framebufferMultisample)
371 {
372 context->handleError(
373 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
374 return false;
375 }
376 break;
377
378 default:
379 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
380 return false;
381 }
382
383 if (length)
384 {
385 *length = 1;
386 }
387 return true;
388}
389
Geoff Langd7d0ed32016-10-07 11:33:51 -0400390bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
391{
392 if (length)
393 {
394 *length = 0;
395 }
396
397 if (GetValidShader(context, shader) == nullptr)
398 {
399 return false;
400 }
401
402 switch (pname)
403 {
404 case GL_SHADER_TYPE:
405 case GL_DELETE_STATUS:
406 case GL_COMPILE_STATUS:
407 case GL_INFO_LOG_LENGTH:
408 case GL_SHADER_SOURCE_LENGTH:
409 break;
410
411 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
412 if (!context->getExtensions().translatedShaderSource)
413 {
414 context->handleError(
415 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
416 return false;
417 }
418 break;
419
420 default:
421 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
422 return false;
423 }
424
425 if (length)
426 {
427 *length = 1;
428 }
429 return true;
430}
431
Geoff Langc1984ed2016-10-07 12:41:00 -0400432bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
433{
434 if (length)
435 {
436 *length = 0;
437 }
438
439 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
440 {
441 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
442 return false;
443 }
444
445 if (context->getTargetTexture(target) == nullptr)
446 {
447 // Should only be possible for external textures
448 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
449 return false;
450 }
451
452 switch (pname)
453 {
454 case GL_TEXTURE_MAG_FILTER:
455 case GL_TEXTURE_MIN_FILTER:
456 case GL_TEXTURE_WRAP_S:
457 case GL_TEXTURE_WRAP_T:
458 break;
459
460 case GL_TEXTURE_USAGE_ANGLE:
461 if (!context->getExtensions().textureUsage)
462 {
463 context->handleError(
464 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
465 return false;
466 }
467 break;
468
469 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
470 if (!context->getExtensions().textureFilterAnisotropic)
471 {
472 context->handleError(
473 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
474 return false;
475 }
476 break;
477
478 case GL_TEXTURE_IMMUTABLE_FORMAT:
479 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
480 {
481 context->handleError(
482 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
483 return false;
484 }
485 break;
486
487 case GL_TEXTURE_WRAP_R:
488 case GL_TEXTURE_IMMUTABLE_LEVELS:
489 case GL_TEXTURE_SWIZZLE_R:
490 case GL_TEXTURE_SWIZZLE_G:
491 case GL_TEXTURE_SWIZZLE_B:
492 case GL_TEXTURE_SWIZZLE_A:
493 case GL_TEXTURE_BASE_LEVEL:
494 case GL_TEXTURE_MAX_LEVEL:
495 case GL_TEXTURE_MIN_LOD:
496 case GL_TEXTURE_MAX_LOD:
497 case GL_TEXTURE_COMPARE_MODE:
498 case GL_TEXTURE_COMPARE_FUNC:
499 if (context->getClientMajorVersion() < 3)
500 {
501 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
502 return false;
503 }
504 break;
505
Geoff Lang81c6b572016-10-19 14:07:52 -0700506 case GL_TEXTURE_SRGB_DECODE_EXT:
507 if (!context->getExtensions().textureSRGBDecode)
508 {
509 context->handleError(
510 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
511 return false;
512 }
513 break;
514
Geoff Langc1984ed2016-10-07 12:41:00 -0400515 default:
516 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
517 return false;
518 }
519
520 if (length)
521 {
522 *length = 1;
523 }
524 return true;
525}
526
527template <typename ParamType>
528bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
529{
530 switch (ConvertToGLenum(params[0]))
531 {
532 case GL_CLAMP_TO_EDGE:
533 break;
534
535 case GL_REPEAT:
536 case GL_MIRRORED_REPEAT:
537 if (isExternalTextureTarget)
538 {
539 // OES_EGL_image_external specifies this error.
540 context->handleError(Error(
541 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
542 return false;
543 }
544 break;
545
546 default:
547 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
548 return false;
549 }
550
551 return true;
552}
553
554template <typename ParamType>
555bool ValidateTextureMinFilterValue(Context *context,
556 ParamType *params,
557 bool isExternalTextureTarget)
558{
559 switch (ConvertToGLenum(params[0]))
560 {
561 case GL_NEAREST:
562 case GL_LINEAR:
563 break;
564
565 case GL_NEAREST_MIPMAP_NEAREST:
566 case GL_LINEAR_MIPMAP_NEAREST:
567 case GL_NEAREST_MIPMAP_LINEAR:
568 case GL_LINEAR_MIPMAP_LINEAR:
569 if (isExternalTextureTarget)
570 {
571 // OES_EGL_image_external specifies this error.
572 context->handleError(
573 Error(GL_INVALID_ENUM,
574 "external textures only support NEAREST and LINEAR filtering"));
575 return false;
576 }
577 break;
578
579 default:
580 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
581 return false;
582 }
583
584 return true;
585}
586
587template <typename ParamType>
588bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
589{
590 switch (ConvertToGLenum(params[0]))
591 {
592 case GL_NEAREST:
593 case GL_LINEAR:
594 break;
595
596 default:
597 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
598 return false;
599 }
600
601 return true;
602}
603
604template <typename ParamType>
605bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
606{
607 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
608 switch (ConvertToGLenum(params[0]))
609 {
610 case GL_NONE:
611 case GL_COMPARE_REF_TO_TEXTURE:
612 break;
613
614 default:
615 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
616 return false;
617 }
618
619 return true;
620}
621
622template <typename ParamType>
623bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
624{
625 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
626 switch (ConvertToGLenum(params[0]))
627 {
628 case GL_LEQUAL:
629 case GL_GEQUAL:
630 case GL_LESS:
631 case GL_GREATER:
632 case GL_EQUAL:
633 case GL_NOTEQUAL:
634 case GL_ALWAYS:
635 case GL_NEVER:
636 break;
637
638 default:
639 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
640 return false;
641 }
642
643 return true;
644}
645
646template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700647bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
648{
649 if (!context->getExtensions().textureSRGBDecode)
650 {
651 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
652 return false;
653 }
654
655 switch (ConvertToGLenum(params[0]))
656 {
657 case GL_DECODE_EXT:
658 case GL_SKIP_DECODE_EXT:
659 break;
660
661 default:
662 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
663 return false;
664 }
665
666 return true;
667}
668
669template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400670bool ValidateTexParameterBase(Context *context,
671 GLenum target,
672 GLenum pname,
673 GLsizei bufSize,
674 ParamType *params)
675{
676 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
677 {
678 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
679 return false;
680 }
681
682 if (context->getTargetTexture(target) == nullptr)
683 {
684 // Should only be possible for external textures
685 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
686 return false;
687 }
688
689 const GLsizei minBufSize = 1;
690 if (bufSize >= 0 && bufSize < minBufSize)
691 {
692 context->handleError(
693 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
694 return false;
695 }
696
697 switch (pname)
698 {
699 case GL_TEXTURE_WRAP_R:
700 case GL_TEXTURE_SWIZZLE_R:
701 case GL_TEXTURE_SWIZZLE_G:
702 case GL_TEXTURE_SWIZZLE_B:
703 case GL_TEXTURE_SWIZZLE_A:
704 case GL_TEXTURE_BASE_LEVEL:
705 case GL_TEXTURE_MAX_LEVEL:
706 case GL_TEXTURE_COMPARE_MODE:
707 case GL_TEXTURE_COMPARE_FUNC:
708 case GL_TEXTURE_MIN_LOD:
709 case GL_TEXTURE_MAX_LOD:
710 if (context->getClientMajorVersion() < 3)
711 {
712 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
713 return false;
714 }
715 if (target == GL_TEXTURE_EXTERNAL_OES &&
716 !context->getExtensions().eglImageExternalEssl3)
717 {
718 context->handleError(Error(GL_INVALID_ENUM,
719 "ES3 texture parameters are not available without "
720 "GL_OES_EGL_image_external_essl3."));
721 return false;
722 }
723 break;
724
725 default:
726 break;
727 }
728
729 switch (pname)
730 {
731 case GL_TEXTURE_WRAP_S:
732 case GL_TEXTURE_WRAP_T:
733 case GL_TEXTURE_WRAP_R:
734 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
735 {
736 return false;
737 }
738 break;
739
740 case GL_TEXTURE_MIN_FILTER:
741 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
742 {
743 return false;
744 }
745 break;
746
747 case GL_TEXTURE_MAG_FILTER:
748 if (!ValidateTextureMagFilterValue(context, params))
749 {
750 return false;
751 }
752 break;
753
754 case GL_TEXTURE_USAGE_ANGLE:
755 switch (ConvertToGLenum(params[0]))
756 {
757 case GL_NONE:
758 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
759 break;
760
761 default:
762 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
763 return false;
764 }
765 break;
766
767 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
768 if (!context->getExtensions().textureFilterAnisotropic)
769 {
770 context->handleError(
771 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
772 return false;
773 }
774
775 // we assume the parameter passed to this validation method is truncated, not rounded
776 if (params[0] < 1)
777 {
778 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
779 return false;
780 }
781 break;
782
783 case GL_TEXTURE_MIN_LOD:
784 case GL_TEXTURE_MAX_LOD:
785 // any value is permissible
786 break;
787
788 case GL_TEXTURE_COMPARE_MODE:
789 if (!ValidateTextureCompareModeValue(context, params))
790 {
791 return false;
792 }
793 break;
794
795 case GL_TEXTURE_COMPARE_FUNC:
796 if (!ValidateTextureCompareFuncValue(context, params))
797 {
798 return false;
799 }
800 break;
801
802 case GL_TEXTURE_SWIZZLE_R:
803 case GL_TEXTURE_SWIZZLE_G:
804 case GL_TEXTURE_SWIZZLE_B:
805 case GL_TEXTURE_SWIZZLE_A:
806 switch (ConvertToGLenum(params[0]))
807 {
808 case GL_RED:
809 case GL_GREEN:
810 case GL_BLUE:
811 case GL_ALPHA:
812 case GL_ZERO:
813 case GL_ONE:
814 break;
815
816 default:
817 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
818 return false;
819 }
820 break;
821
822 case GL_TEXTURE_BASE_LEVEL:
823 if (params[0] < 0)
824 {
825 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
826 return false;
827 }
828 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
829 {
830 context->handleError(
831 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
832 return false;
833 }
834 break;
835
836 case GL_TEXTURE_MAX_LEVEL:
837 if (params[0] < 0)
838 {
839 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
840 return false;
841 }
842 break;
843
Geoff Lang3b573612016-10-31 14:08:10 -0400844 case GL_DEPTH_STENCIL_TEXTURE_MODE:
845 if (context->getClientVersion() < Version(3, 1))
846 {
847 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
848 return false;
849 }
Geoff Lang9f090372016-12-02 10:20:43 -0500850 switch (ConvertToGLenum(params[0]))
851 {
852 case GL_DEPTH_COMPONENT:
853 case GL_STENCIL_INDEX:
854 break;
855
856 default:
857 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
858 return false;
859 }
Geoff Lang3b573612016-10-31 14:08:10 -0400860 break;
861
Geoff Lang81c6b572016-10-19 14:07:52 -0700862 case GL_TEXTURE_SRGB_DECODE_EXT:
863 if (!ValidateTextureSRGBDecodeValue(context, params))
864 {
865 return false;
866 }
867 break;
868
Geoff Langc1984ed2016-10-07 12:41:00 -0400869 default:
870 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
871 return false;
872 }
873
874 return true;
875}
876
877template <typename ParamType>
878bool ValidateSamplerParameterBase(Context *context,
879 GLuint sampler,
880 GLenum pname,
881 GLsizei bufSize,
882 ParamType *params)
883{
884 if (context->getClientMajorVersion() < 3)
885 {
886 context->handleError(
887 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
888 return false;
889 }
890
891 if (!context->isSampler(sampler))
892 {
893 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
894 return false;
895 }
896
897 const GLsizei minBufSize = 1;
898 if (bufSize >= 0 && bufSize < minBufSize)
899 {
900 context->handleError(
901 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
902 return false;
903 }
904
905 switch (pname)
906 {
907 case GL_TEXTURE_WRAP_S:
908 case GL_TEXTURE_WRAP_T:
909 case GL_TEXTURE_WRAP_R:
910 if (!ValidateTextureWrapModeValue(context, params, false))
911 {
912 return false;
913 }
914 break;
915
916 case GL_TEXTURE_MIN_FILTER:
917 if (!ValidateTextureMinFilterValue(context, params, false))
918 {
919 return false;
920 }
921 break;
922
923 case GL_TEXTURE_MAG_FILTER:
924 if (!ValidateTextureMagFilterValue(context, params))
925 {
926 return false;
927 }
928 break;
929
930 case GL_TEXTURE_MIN_LOD:
931 case GL_TEXTURE_MAX_LOD:
932 // any value is permissible
933 break;
934
935 case GL_TEXTURE_COMPARE_MODE:
936 if (!ValidateTextureCompareModeValue(context, params))
937 {
938 return false;
939 }
940 break;
941
942 case GL_TEXTURE_COMPARE_FUNC:
943 if (!ValidateTextureCompareFuncValue(context, params))
944 {
945 return false;
946 }
947 break;
948
Geoff Lang81c6b572016-10-19 14:07:52 -0700949 case GL_TEXTURE_SRGB_DECODE_EXT:
950 if (!ValidateTextureSRGBDecodeValue(context, params))
951 {
952 return false;
953 }
954 break;
955
Geoff Langc1984ed2016-10-07 12:41:00 -0400956 default:
957 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
958 return false;
959 }
960
961 return true;
962}
963
964bool ValidateGetSamplerParameterBase(Context *context,
965 GLuint sampler,
966 GLenum pname,
967 GLsizei *length)
968{
969 if (length)
970 {
971 *length = 0;
972 }
973
974 if (context->getClientMajorVersion() < 3)
975 {
976 context->handleError(
977 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
978 return false;
979 }
980
981 if (!context->isSampler(sampler))
982 {
983 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
984 return false;
985 }
986
987 switch (pname)
988 {
989 case GL_TEXTURE_WRAP_S:
990 case GL_TEXTURE_WRAP_T:
991 case GL_TEXTURE_WRAP_R:
992 case GL_TEXTURE_MIN_FILTER:
993 case GL_TEXTURE_MAG_FILTER:
994 case GL_TEXTURE_MIN_LOD:
995 case GL_TEXTURE_MAX_LOD:
996 case GL_TEXTURE_COMPARE_MODE:
997 case GL_TEXTURE_COMPARE_FUNC:
998 break;
999
Geoff Lang81c6b572016-10-19 14:07:52 -07001000 case GL_TEXTURE_SRGB_DECODE_EXT:
1001 if (!context->getExtensions().textureSRGBDecode)
1002 {
1003 context->handleError(
1004 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
1005 return false;
1006 }
1007 break;
1008
Geoff Langc1984ed2016-10-07 12:41:00 -04001009 default:
1010 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1011 return false;
1012 }
1013
1014 if (length)
1015 {
1016 *length = 1;
1017 }
1018 return true;
1019}
1020
Geoff Lang0b031062016-10-13 14:30:04 -04001021bool ValidateGetVertexAttribBase(Context *context,
1022 GLuint index,
1023 GLenum pname,
1024 GLsizei *length,
1025 bool pointer,
1026 bool pureIntegerEntryPoint)
1027{
1028 if (length)
1029 {
1030 *length = 0;
1031 }
1032
1033 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1034 {
1035 context->handleError(
1036 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1037 return false;
1038 }
1039
1040 if (index >= context->getCaps().maxVertexAttributes)
1041 {
1042 context->handleError(Error(
1043 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1044 return false;
1045 }
1046
1047 if (pointer)
1048 {
1049 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1050 {
1051 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1052 return false;
1053 }
1054 }
1055 else
1056 {
1057 switch (pname)
1058 {
1059 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1060 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1061 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1062 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1063 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1064 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1065 case GL_CURRENT_VERTEX_ATTRIB:
1066 break;
1067
1068 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1069 static_assert(
1070 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1071 "ANGLE extension enums not equal to GL enums.");
1072 if (context->getClientMajorVersion() < 3 &&
1073 !context->getExtensions().instancedArrays)
1074 {
1075 context->handleError(Error(GL_INVALID_ENUM,
1076 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1077 "3.0 or GL_ANGLE_instanced_arrays."));
1078 return false;
1079 }
1080 break;
1081
1082 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1083 if (context->getClientMajorVersion() < 3)
1084 {
1085 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1086 return false;
1087 }
1088 break;
1089
1090 default:
1091 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1092 return false;
1093 }
1094 }
1095
1096 if (length)
1097 {
1098 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1099 {
1100 *length = 4;
1101 }
1102 else
1103 {
1104 *length = 1;
1105 }
1106 }
1107
1108 return true;
1109}
1110
Geoff Lang6899b872016-10-14 11:30:13 -04001111bool ValidateGetActiveUniformBlockivBase(Context *context,
1112 GLuint program,
1113 GLuint uniformBlockIndex,
1114 GLenum pname,
1115 GLsizei *length)
1116{
1117 if (length)
1118 {
1119 *length = 0;
1120 }
1121
1122 if (context->getClientMajorVersion() < 3)
1123 {
1124 context->handleError(
1125 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1126 return false;
1127 }
1128
1129 Program *programObject = GetValidProgram(context, program);
1130 if (!programObject)
1131 {
1132 return false;
1133 }
1134
1135 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1136 {
1137 context->handleError(
1138 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1139 return false;
1140 }
1141
1142 switch (pname)
1143 {
1144 case GL_UNIFORM_BLOCK_BINDING:
1145 case GL_UNIFORM_BLOCK_DATA_SIZE:
1146 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1147 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1148 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1149 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1150 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1151 break;
1152
1153 default:
1154 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1155 return false;
1156 }
1157
1158 if (length)
1159 {
1160 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1161 {
1162 const UniformBlock &uniformBlock =
1163 programObject->getUniformBlockByIndex(uniformBlockIndex);
1164 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1165 }
1166 else
1167 {
1168 *length = 1;
1169 }
1170 }
1171
1172 return true;
1173}
1174
Geoff Langebebe1c2016-10-14 12:01:31 -04001175bool ValidateGetBufferParameterBase(ValidationContext *context,
1176 GLenum target,
1177 GLenum pname,
1178 bool pointerVersion,
1179 GLsizei *numParams)
1180{
1181 if (numParams)
1182 {
1183 *numParams = 0;
1184 }
1185
1186 if (!ValidBufferTarget(context, target))
1187 {
1188 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1189 return false;
1190 }
1191
1192 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1193 if (!buffer)
1194 {
1195 // A null buffer means that "0" is bound to the requested buffer target
1196 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1197 return false;
1198 }
1199
1200 const Extensions &extensions = context->getExtensions();
1201
1202 switch (pname)
1203 {
1204 case GL_BUFFER_USAGE:
1205 case GL_BUFFER_SIZE:
1206 break;
1207
1208 case GL_BUFFER_ACCESS_OES:
1209 if (!extensions.mapBuffer)
1210 {
1211 context->handleError(
1212 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
1213 return false;
1214 }
1215 break;
1216
1217 case GL_BUFFER_MAPPED:
1218 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1219 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1220 !extensions.mapBufferRange)
1221 {
1222 context->handleError(Error(
1223 GL_INVALID_ENUM,
1224 "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
1225 return false;
1226 }
1227 break;
1228
1229 case GL_BUFFER_MAP_POINTER:
1230 if (!pointerVersion)
1231 {
1232 context->handleError(
1233 Error(GL_INVALID_ENUM,
1234 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1235 return false;
1236 }
1237 break;
1238
1239 case GL_BUFFER_ACCESS_FLAGS:
1240 case GL_BUFFER_MAP_OFFSET:
1241 case GL_BUFFER_MAP_LENGTH:
1242 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1243 {
1244 context->handleError(Error(
1245 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1246 return false;
1247 }
1248 break;
1249
1250 default:
1251 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1252 return false;
1253 }
1254
1255 // All buffer parameter queries return one value.
1256 if (numParams)
1257 {
1258 *numParams = 1;
1259 }
1260
1261 return true;
1262}
1263
Geoff Lang0a9661f2016-10-20 10:59:20 -07001264bool ValidateGetInternalFormativBase(Context *context,
1265 GLenum target,
1266 GLenum internalformat,
1267 GLenum pname,
1268 GLsizei bufSize,
1269 GLsizei *numParams)
1270{
1271 if (numParams)
1272 {
1273 *numParams = 0;
1274 }
1275
1276 if (context->getClientMajorVersion() < 3)
1277 {
1278 context->handleError(
1279 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1280 return false;
1281 }
1282
1283 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1284 if (!formatCaps.renderable)
1285 {
1286 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1287 return false;
1288 }
1289
1290 switch (target)
1291 {
1292 case GL_RENDERBUFFER:
1293 break;
1294
1295 default:
1296 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1297 return false;
1298 }
1299
1300 if (bufSize < 0)
1301 {
1302 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1303 return false;
1304 }
1305
1306 GLsizei maxWriteParams = 0;
1307 switch (pname)
1308 {
1309 case GL_NUM_SAMPLE_COUNTS:
1310 maxWriteParams = 1;
1311 break;
1312
1313 case GL_SAMPLES:
1314 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1315 break;
1316
1317 default:
1318 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1319 return false;
1320 }
1321
1322 if (numParams)
1323 {
1324 // glGetInternalFormativ will not overflow bufSize
1325 *numParams = std::min(bufSize, maxWriteParams);
1326 }
1327
1328 return true;
1329}
1330
Geoff Langf41a7152016-09-19 15:11:17 -04001331} // anonymous namespace
1332
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001333bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001334{
Jamie Madilld7460c72014-01-21 16:38:14 -05001335 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001336 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001337 case GL_TEXTURE_2D:
1338 case GL_TEXTURE_CUBE_MAP:
1339 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001340
He Yunchaoced53ae2016-11-29 15:00:51 +08001341 case GL_TEXTURE_3D:
1342 case GL_TEXTURE_2D_ARRAY:
1343 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001344
He Yunchaoced53ae2016-11-29 15:00:51 +08001345 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001346 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001347
He Yunchaoced53ae2016-11-29 15:00:51 +08001348 default:
1349 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001350 }
Jamie Madill35d15012013-10-07 10:46:37 -04001351}
1352
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001353bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1354{
1355 switch (target)
1356 {
1357 case GL_TEXTURE_2D:
1358 case GL_TEXTURE_CUBE_MAP:
1359 return true;
1360
1361 default:
1362 return false;
1363 }
1364}
1365
1366bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1367{
1368 switch (target)
1369 {
1370 case GL_TEXTURE_3D:
1371 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001372 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001373
1374 default:
1375 return false;
1376 }
1377}
1378
Ian Ewellbda75592016-04-18 17:25:54 -04001379// Most texture GL calls are not compatible with external textures, so we have a separate validation
1380// function for use in the GL calls that do
1381bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1382{
1383 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1384 (context->getExtensions().eglImageExternal ||
1385 context->getExtensions().eglStreamConsumerExternal);
1386}
1387
Shannon Woods4dfed832014-03-17 20:03:39 -04001388// This function differs from ValidTextureTarget in that the target must be
1389// usable as the destination of a 2D operation-- so a cube face is valid, but
1390// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001391// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001392bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001393{
1394 switch (target)
1395 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001396 case GL_TEXTURE_2D:
1397 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1398 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1399 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1400 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1401 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1402 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1403 return true;
1404 default:
1405 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001406 }
1407}
1408
1409bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1410{
1411 switch (target)
1412 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001413 case GL_TEXTURE_3D:
1414 case GL_TEXTURE_2D_ARRAY:
1415 return true;
1416 default:
1417 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001418 }
1419}
1420
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001421bool ValidFramebufferTarget(GLenum target)
1422{
He Yunchaoced53ae2016-11-29 15:00:51 +08001423 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1424 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001425 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001426
1427 switch (target)
1428 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001429 case GL_FRAMEBUFFER:
1430 return true;
1431 case GL_READ_FRAMEBUFFER:
1432 return true;
1433 case GL_DRAW_FRAMEBUFFER:
1434 return true;
1435 default:
1436 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001437 }
1438}
1439
Jamie Madill29639852016-09-02 15:00:09 -04001440bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001441{
1442 switch (target)
1443 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001444 case GL_ARRAY_BUFFER:
1445 case GL_ELEMENT_ARRAY_BUFFER:
1446 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001447
He Yunchaoced53ae2016-11-29 15:00:51 +08001448 case GL_PIXEL_PACK_BUFFER:
1449 case GL_PIXEL_UNPACK_BUFFER:
1450 return (context->getExtensions().pixelBufferObject ||
1451 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001452
He Yunchaoced53ae2016-11-29 15:00:51 +08001453 case GL_COPY_READ_BUFFER:
1454 case GL_COPY_WRITE_BUFFER:
1455 case GL_TRANSFORM_FEEDBACK_BUFFER:
1456 case GL_UNIFORM_BUFFER:
1457 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001458
He Yunchaoced53ae2016-11-29 15:00:51 +08001459 case GL_ATOMIC_COUNTER_BUFFER:
1460 case GL_SHADER_STORAGE_BUFFER:
1461 case GL_DRAW_INDIRECT_BUFFER:
1462 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001463 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001464
He Yunchaoced53ae2016-11-29 15:00:51 +08001465 default:
1466 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001467 }
1468}
1469
Jamie Madillc29968b2016-01-20 11:17:23 -05001470bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001471{
Jamie Madillc29968b2016-01-20 11:17:23 -05001472 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001473 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001474 switch (target)
1475 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001476 case GL_TEXTURE_2D:
1477 maxDimension = caps.max2DTextureSize;
1478 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001479 case GL_TEXTURE_CUBE_MAP:
1480 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1481 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1482 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1483 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1484 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1485 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1486 maxDimension = caps.maxCubeMapTextureSize;
1487 break;
1488 case GL_TEXTURE_3D:
1489 maxDimension = caps.max3DTextureSize;
1490 break;
1491 case GL_TEXTURE_2D_ARRAY:
1492 maxDimension = caps.max2DTextureSize;
1493 break;
1494 default:
1495 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001496 }
1497
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001498 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001499}
1500
Geoff Langcc507aa2016-12-12 10:09:52 -05001501bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001502 GLenum target,
1503 GLint level,
1504 GLsizei width,
1505 GLsizei height,
1506 GLsizei depth,
1507 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001508{
1509 if (level < 0 || width < 0 || height < 0 || depth < 0)
1510 {
1511 return false;
1512 }
1513
Austin Kinross08528e12015-10-07 16:24:40 -07001514 // TexSubImage parameters can be NPOT without textureNPOT extension,
1515 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001516 bool hasNPOTSupport =
1517 context->getExtensions().textureNPOT && context->getClientVersion() >= Version(3, 0);
1518 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001519 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001520 {
1521 return false;
1522 }
1523
1524 if (!ValidMipLevel(context, target, level))
1525 {
1526 return false;
1527 }
1528
1529 return true;
1530}
1531
Geoff Lang0d8b7242015-09-09 14:56:53 -04001532bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1533{
1534 // List of compressed format that require that the texture size is smaller than or a multiple of
1535 // the compressed block size.
1536 switch (internalFormat)
1537 {
1538 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1539 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1540 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1541 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001542 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001543 return true;
1544
1545 default:
1546 return false;
1547 }
1548}
1549
Jamie Madillc29968b2016-01-20 11:17:23 -05001550bool ValidCompressedImageSize(const ValidationContext *context,
1551 GLenum internalFormat,
1552 GLsizei width,
1553 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001554{
Geoff Lang5d601382014-07-22 15:14:06 -04001555 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1556 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001557 {
1558 return false;
1559 }
1560
Geoff Lang0d8b7242015-09-09 14:56:53 -04001561 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001562 {
1563 return false;
1564 }
1565
Geoff Lang0d8b7242015-09-09 14:56:53 -04001566 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1567 {
1568 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1569 width % formatInfo.compressedBlockWidth != 0) ||
1570 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1571 height % formatInfo.compressedBlockHeight != 0))
1572 {
1573 return false;
1574 }
1575 }
1576
Geoff Langd4f180b2013-09-24 13:57:44 -04001577 return true;
1578}
1579
Geoff Langff5b2d52016-09-07 11:32:23 -04001580bool ValidImageDataSize(ValidationContext *context,
1581 GLenum textureTarget,
1582 GLsizei width,
1583 GLsizei height,
1584 GLsizei depth,
1585 GLenum internalFormat,
1586 GLenum type,
1587 const GLvoid *pixels,
1588 GLsizei imageSize)
1589{
1590 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1591 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1592 {
1593 // Checks are not required
1594 return true;
1595 }
1596
1597 // ...the data would be unpacked from the buffer object such that the memory reads required
1598 // would exceed the data store size.
1599 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1600 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1601 const gl::Extents size(width, height, depth);
1602 const auto &unpack = context->getGLState().getUnpackState();
1603
1604 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1605 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1606 if (endByteOrErr.isError())
1607 {
1608 context->handleError(endByteOrErr.getError());
1609 return false;
1610 }
1611
1612 GLuint endByte = endByteOrErr.getResult();
1613
1614 if (pixelUnpackBuffer)
1615 {
1616 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1617 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1618 checkedEndByte += checkedOffset;
1619
1620 if (!checkedEndByte.IsValid() ||
1621 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1622 {
1623 // Overflow past the end of the buffer
1624 context->handleError(Error(GL_INVALID_OPERATION));
1625 return false;
1626 }
1627 }
1628 else
1629 {
1630 ASSERT(imageSize >= 0);
1631 if (pixels == nullptr && imageSize != 0)
1632 {
1633 context->handleError(
1634 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001635 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001636 }
1637
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001638 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001639 {
1640 context->handleError(
1641 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1642 return false;
1643 }
1644 }
1645
1646 return true;
1647}
1648
Geoff Lang37dde692014-01-31 16:34:54 -05001649bool ValidQueryType(const Context *context, GLenum queryType)
1650{
He Yunchaoced53ae2016-11-29 15:00:51 +08001651 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1652 "GL extension enums not equal.");
1653 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1654 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001655
1656 switch (queryType)
1657 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001658 case GL_ANY_SAMPLES_PASSED:
1659 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1660 return true;
1661 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1662 return (context->getClientMajorVersion() >= 3);
1663 case GL_TIME_ELAPSED_EXT:
1664 return context->getExtensions().disjointTimerQuery;
1665 case GL_COMMANDS_COMPLETED_CHROMIUM:
1666 return context->getExtensions().syncQuery;
1667 default:
1668 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001669 }
1670}
1671
Jamie Madillef300b12016-10-07 15:12:09 -04001672Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001673{
He Yunchaoced53ae2016-11-29 15:00:51 +08001674 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1675 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1676 // or program object and INVALID_OPERATION if the provided name identifies an object
1677 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001678
Dian Xiang769769a2015-09-09 15:20:08 -07001679 Program *validProgram = context->getProgram(id);
1680
1681 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001682 {
Dian Xiang769769a2015-09-09 15:20:08 -07001683 if (context->getShader(id))
1684 {
Jamie Madill437fa652016-05-03 15:13:24 -04001685 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001686 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1687 }
1688 else
1689 {
Jamie Madill437fa652016-05-03 15:13:24 -04001690 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001691 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001692 }
Dian Xiang769769a2015-09-09 15:20:08 -07001693
1694 return validProgram;
1695}
1696
Jamie Madillef300b12016-10-07 15:12:09 -04001697Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001698{
1699 // See ValidProgram for spec details.
1700
1701 Shader *validShader = context->getShader(id);
1702
1703 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001704 {
Dian Xiang769769a2015-09-09 15:20:08 -07001705 if (context->getProgram(id))
1706 {
Jamie Madill437fa652016-05-03 15:13:24 -04001707 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001708 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1709 }
1710 else
1711 {
Jamie Madill437fa652016-05-03 15:13:24 -04001712 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001713 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001714 }
Dian Xiang769769a2015-09-09 15:20:08 -07001715
1716 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001717}
1718
Geoff Langb1196682014-07-23 13:47:29 -04001719bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001720{
1721 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1722 {
1723 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1724
Geoff Langaae65a42014-05-26 12:43:44 -04001725 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001726 {
Jamie Madill437fa652016-05-03 15:13:24 -04001727 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001728 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001729 }
1730 }
1731 else
1732 {
1733 switch (attachment)
1734 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001735 case GL_DEPTH_ATTACHMENT:
1736 case GL_STENCIL_ATTACHMENT:
1737 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001738
He Yunchaoced53ae2016-11-29 15:00:51 +08001739 case GL_DEPTH_STENCIL_ATTACHMENT:
1740 if (!context->getExtensions().webglCompatibility &&
1741 context->getClientMajorVersion() < 3)
1742 {
1743 context->handleError(Error(GL_INVALID_ENUM));
1744 return false;
1745 }
1746 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001747
He Yunchaoced53ae2016-11-29 15:00:51 +08001748 default:
1749 context->handleError(Error(GL_INVALID_ENUM));
1750 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001751 }
1752 }
1753
1754 return true;
1755}
1756
He Yunchaoced53ae2016-11-29 15:00:51 +08001757bool ValidateRenderbufferStorageParametersBase(gl::Context *context,
1758 GLenum target,
1759 GLsizei samples,
1760 GLenum internalformat,
1761 GLsizei width,
1762 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001763{
1764 switch (target)
1765 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001766 case GL_RENDERBUFFER:
1767 break;
1768 default:
1769 context->handleError(Error(GL_INVALID_ENUM));
1770 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001771 }
1772
1773 if (width < 0 || height < 0 || samples < 0)
1774 {
Jamie Madill437fa652016-05-03 15:13:24 -04001775 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001776 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001777 }
1778
Geoff Langd87878e2014-09-19 15:42:59 -04001779 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1780 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001781 {
Jamie Madill437fa652016-05-03 15:13:24 -04001782 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001783 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001784 }
1785
1786 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1787 // 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 -08001788 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001789 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001790 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001791 {
Jamie Madill437fa652016-05-03 15:13:24 -04001792 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001793 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001794 }
1795
Geoff Langaae65a42014-05-26 12:43:44 -04001796 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001797 {
Jamie Madill437fa652016-05-03 15:13:24 -04001798 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001799 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001800 }
1801
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001802 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001803 if (handle == 0)
1804 {
Jamie Madill437fa652016-05-03 15:13:24 -04001805 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001806 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001807 }
1808
1809 return true;
1810}
1811
He Yunchaoced53ae2016-11-29 15:00:51 +08001812bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context,
1813 GLenum target,
1814 GLsizei samples,
1815 GLenum internalformat,
1816 GLsizei width,
1817 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -08001818{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001819 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001820
1821 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001822 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001823 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001824 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001825 {
Jamie Madill437fa652016-05-03 15:13:24 -04001826 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001827 return false;
1828 }
1829
1830 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1831 // the specified storage. This is different than ES 3.0 in which a sample number higher
1832 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001833 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001834 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001835 {
Geoff Langa4903b72015-03-02 16:02:48 -08001836 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1837 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1838 {
Jamie Madill437fa652016-05-03 15:13:24 -04001839 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001840 return false;
1841 }
Corentin Walleze0902642014-11-04 12:32:15 -08001842 }
1843
He Yunchaoced53ae2016-11-29 15:00:51 +08001844 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
1845 width, height);
Corentin Walleze0902642014-11-04 12:32:15 -08001846}
1847
He Yunchaoced53ae2016-11-29 15:00:51 +08001848bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1849 GLenum target,
1850 GLenum attachment,
1851 GLenum renderbuffertarget,
1852 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001853{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001854 if (!ValidFramebufferTarget(target))
1855 {
Jamie Madill437fa652016-05-03 15:13:24 -04001856 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001857 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001858 }
1859
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001860 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001861
Jamie Madill84115c92015-04-23 15:00:07 -04001862 ASSERT(framebuffer);
1863 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001864 {
Jamie Madill437fa652016-05-03 15:13:24 -04001865 context->handleError(
1866 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001867 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001868 }
1869
Jamie Madillb4472272014-07-03 10:38:55 -04001870 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001871 {
Jamie Madillb4472272014-07-03 10:38:55 -04001872 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001873 }
1874
Jamie Madillab9d82c2014-01-21 16:38:14 -05001875 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1876 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1877 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1878 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1879 if (renderbuffer != 0)
1880 {
1881 if (!context->getRenderbuffer(renderbuffer))
1882 {
Jamie Madill437fa652016-05-03 15:13:24 -04001883 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001884 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001885 }
1886 }
1887
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001888 return true;
1889}
1890
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001891bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001892 GLint srcX0,
1893 GLint srcY0,
1894 GLint srcX1,
1895 GLint srcY1,
1896 GLint dstX0,
1897 GLint dstY0,
1898 GLint dstX1,
1899 GLint dstY1,
1900 GLbitfield mask,
1901 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001902{
1903 switch (filter)
1904 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001905 case GL_NEAREST:
1906 break;
1907 case GL_LINEAR:
1908 break;
1909 default:
1910 context->handleError(Error(GL_INVALID_ENUM));
1911 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001912 }
1913
1914 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1915 {
Jamie Madill437fa652016-05-03 15:13:24 -04001916 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001917 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001918 }
1919
1920 if (mask == 0)
1921 {
1922 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1923 // buffers are copied.
1924 return false;
1925 }
1926
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001927 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1928 // color buffer, leaving only nearest being unfiltered from above
1929 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1930 {
Jamie Madill437fa652016-05-03 15:13:24 -04001931 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001932 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001933 }
1934
Jamie Madill51f40ec2016-06-15 14:06:00 -04001935 const auto &glState = context->getGLState();
1936 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1937 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001938
1939 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001940 {
Jamie Madill437fa652016-05-03 15:13:24 -04001941 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001942 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001943 }
1944
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001945 if (readFramebuffer->id() == drawFramebuffer->id())
1946 {
1947 context->handleError(Error(GL_INVALID_OPERATION));
1948 return false;
1949 }
1950
Jamie Madill51f40ec2016-06-15 14:06:00 -04001951 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001952 {
Jamie Madill437fa652016-05-03 15:13:24 -04001953 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001954 return false;
1955 }
1956
Jamie Madill51f40ec2016-06-15 14:06:00 -04001957 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001958 {
Jamie Madill437fa652016-05-03 15:13:24 -04001959 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001960 return false;
1961 }
1962
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001963 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001964 {
Jamie Madill437fa652016-05-03 15:13:24 -04001965 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001966 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001967 }
1968
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001969 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1970
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001971 if (mask & GL_COLOR_BUFFER_BIT)
1972 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001973 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1974 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001975 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001976
1977 if (readColorBuffer && drawColorBuffer)
1978 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001979 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001980
Geoff Langa15472a2015-08-11 11:48:03 -04001981 for (size_t drawbufferIdx = 0;
1982 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001983 {
Geoff Langa15472a2015-08-11 11:48:03 -04001984 const FramebufferAttachment *attachment =
1985 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1986 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001987 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001988 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001989
Geoff Langb2f3d052013-08-13 12:49:27 -04001990 // The GL ES 3.0.2 spec (pg 193) states that:
1991 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001992 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1993 // as well
1994 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1995 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001996 // Changes with EXT_color_buffer_float:
1997 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001998 GLenum readComponentType = readFormat.info->componentType;
1999 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08002000 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05002001 readComponentType == GL_SIGNED_NORMALIZED);
2002 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
2003 drawComponentType == GL_SIGNED_NORMALIZED);
2004
2005 if (extensions.colorBufferFloat)
2006 {
2007 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2008 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2009
2010 if (readFixedOrFloat != drawFixedOrFloat)
2011 {
Jamie Madill437fa652016-05-03 15:13:24 -04002012 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002013 "If the read buffer contains fixed-point or "
2014 "floating-point values, the draw buffer "
2015 "must as well."));
2016 return false;
2017 }
2018 }
2019 else if (readFixedPoint != drawFixedPoint)
2020 {
Jamie Madill437fa652016-05-03 15:13:24 -04002021 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002022 "If the read buffer contains fixed-point "
2023 "values, the draw buffer must as well."));
2024 return false;
2025 }
2026
2027 if (readComponentType == GL_UNSIGNED_INT &&
2028 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002029 {
Jamie Madill437fa652016-05-03 15:13:24 -04002030 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002031 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002032 }
2033
Jamie Madill6163c752015-12-07 16:32:59 -05002034 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002035 {
Jamie Madill437fa652016-05-03 15:13:24 -04002036 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002037 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002038 }
2039
Jamie Madilla3944d42016-07-22 22:13:26 -04002040 if (readColorBuffer->getSamples() > 0 &&
2041 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002042 {
Jamie Madill437fa652016-05-03 15:13:24 -04002043 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002044 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002045 }
2046 }
2047 }
2048
Jamie Madilla3944d42016-07-22 22:13:26 -04002049 if ((readFormat.info->componentType == GL_INT ||
2050 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2051 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002052 {
Jamie Madill437fa652016-05-03 15:13:24 -04002053 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002054 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002055 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002056 }
2057 }
2058
He Yunchaoced53ae2016-11-29 15:00:51 +08002059 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002060 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2061 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002062 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002063 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002064 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002065 const gl::FramebufferAttachment *readBuffer =
2066 readFramebuffer->getAttachment(attachments[i]);
2067 const gl::FramebufferAttachment *drawBuffer =
2068 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002069
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002070 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002071 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002072 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002073 {
Jamie Madill437fa652016-05-03 15:13:24 -04002074 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002075 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002076 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002077
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002078 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002079 {
Jamie Madill437fa652016-05-03 15:13:24 -04002080 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002081 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002082 }
2083 }
2084 }
2085 }
2086
2087 return true;
2088}
2089
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002090bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002091 GLint x,
2092 GLint y,
2093 GLsizei width,
2094 GLsizei height,
2095 GLenum format,
2096 GLenum type,
2097 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002098{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002099 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2100}
2101
2102bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2103 GLint x,
2104 GLint y,
2105 GLsizei width,
2106 GLsizei height,
2107 GLenum format,
2108 GLenum type,
2109 GLsizei bufSize,
2110 GLsizei *length,
2111 GLvoid *pixels)
2112{
2113 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002114 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002115 return false;
2116 }
2117
Geoff Lang62fce5b2016-09-30 10:46:35 -04002118 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2119 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002120 {
Geoff Langb1196682014-07-23 13:47:29 -04002121 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002122 }
2123
Geoff Lang62fce5b2016-09-30 10:46:35 -04002124 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002125 {
Geoff Langb1196682014-07-23 13:47:29 -04002126 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002127 }
2128
Jamie Madillc29968b2016-01-20 11:17:23 -05002129 return true;
2130}
2131
2132bool ValidateReadnPixelsEXT(Context *context,
2133 GLint x,
2134 GLint y,
2135 GLsizei width,
2136 GLsizei height,
2137 GLenum format,
2138 GLenum type,
2139 GLsizei bufSize,
2140 GLvoid *pixels)
2141{
2142 if (bufSize < 0)
2143 {
Jamie Madill437fa652016-05-03 15:13:24 -04002144 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002145 return false;
2146 }
2147
Geoff Lang62fce5b2016-09-30 10:46:35 -04002148 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2149 pixels);
2150}
Jamie Madill26e91952014-03-05 15:01:27 -05002151
Geoff Lang62fce5b2016-09-30 10:46:35 -04002152bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2153 GLint x,
2154 GLint y,
2155 GLsizei width,
2156 GLsizei height,
2157 GLenum format,
2158 GLenum type,
2159 GLsizei bufSize,
2160 GLsizei *length,
2161 GLvoid *data)
2162{
2163 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002164 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002165 return false;
2166 }
2167
Geoff Lang62fce5b2016-09-30 10:46:35 -04002168 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002169 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002170 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002171 }
2172
Geoff Lang62fce5b2016-09-30 10:46:35 -04002173 if (!ValidateRobustBufferSize(context, bufSize, *length))
2174 {
2175 return false;
2176 }
2177
2178 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002179}
2180
Olli Etuaho41997e72016-03-10 13:38:39 +02002181bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002182{
2183 if (!context->getExtensions().occlusionQueryBoolean &&
2184 !context->getExtensions().disjointTimerQuery)
2185 {
Jamie Madill437fa652016-05-03 15:13:24 -04002186 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002187 return false;
2188 }
2189
Olli Etuaho41997e72016-03-10 13:38:39 +02002190 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002191}
2192
Olli Etuaho41997e72016-03-10 13:38:39 +02002193bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002194{
2195 if (!context->getExtensions().occlusionQueryBoolean &&
2196 !context->getExtensions().disjointTimerQuery)
2197 {
Jamie Madill437fa652016-05-03 15:13:24 -04002198 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002199 return false;
2200 }
2201
Olli Etuaho41997e72016-03-10 13:38:39 +02002202 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002203}
2204
2205bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002206{
2207 if (!ValidQueryType(context, target))
2208 {
Jamie Madill437fa652016-05-03 15:13:24 -04002209 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002210 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002211 }
2212
2213 if (id == 0)
2214 {
Jamie Madill437fa652016-05-03 15:13:24 -04002215 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002216 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002217 }
2218
2219 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2220 // of zero, if the active query object name for <target> is non-zero (for the
2221 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2222 // the active query for either target is non-zero), if <id> is the name of an
2223 // existing query object whose type does not match <target>, or if <id> is the
2224 // active query object name for any query type, the error INVALID_OPERATION is
2225 // generated.
2226
2227 // Ensure no other queries are active
2228 // NOTE: If other queries than occlusion are supported, we will need to check
2229 // separately that:
2230 // a) The query ID passed is not the current active query for any target/type
2231 // b) There are no active queries for the requested target (and in the case
2232 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2233 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002234
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002235 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002236 {
Jamie Madill437fa652016-05-03 15:13:24 -04002237 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002238 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002239 }
2240
2241 Query *queryObject = context->getQuery(id, true, target);
2242
2243 // check that name was obtained with glGenQueries
2244 if (!queryObject)
2245 {
Jamie Madill437fa652016-05-03 15:13:24 -04002246 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002247 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002248 }
2249
2250 // check for type mismatch
2251 if (queryObject->getType() != target)
2252 {
Jamie Madill437fa652016-05-03 15:13:24 -04002253 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002254 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002255 }
2256
2257 return true;
2258}
2259
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002260bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2261{
2262 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002263 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002264 {
Jamie Madill437fa652016-05-03 15:13:24 -04002265 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002266 return false;
2267 }
2268
2269 return ValidateBeginQueryBase(context, target, id);
2270}
2271
2272bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002273{
2274 if (!ValidQueryType(context, target))
2275 {
Jamie Madill437fa652016-05-03 15:13:24 -04002276 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002277 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002278 }
2279
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002280 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002281
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002282 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002283 {
Jamie Madill437fa652016-05-03 15:13:24 -04002284 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002285 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002286 }
2287
Jamie Madill45c785d2014-05-13 14:09:34 -04002288 return true;
2289}
2290
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002291bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2292{
2293 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002294 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002295 {
Jamie Madill437fa652016-05-03 15:13:24 -04002296 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002297 return false;
2298 }
2299
2300 return ValidateEndQueryBase(context, target);
2301}
2302
2303bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2304{
2305 if (!context->getExtensions().disjointTimerQuery)
2306 {
Jamie Madill437fa652016-05-03 15:13:24 -04002307 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002308 return false;
2309 }
2310
2311 if (target != GL_TIMESTAMP_EXT)
2312 {
Jamie Madill437fa652016-05-03 15:13:24 -04002313 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002314 return false;
2315 }
2316
2317 Query *queryObject = context->getQuery(id, true, target);
2318 if (queryObject == nullptr)
2319 {
Jamie Madill437fa652016-05-03 15:13:24 -04002320 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002321 return false;
2322 }
2323
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002324 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002325 {
Jamie Madill437fa652016-05-03 15:13:24 -04002326 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002327 return false;
2328 }
2329
2330 return true;
2331}
2332
Geoff Lang2186c382016-10-14 10:54:54 -04002333bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002334{
Geoff Lang2186c382016-10-14 10:54:54 -04002335 if (numParams)
2336 {
2337 *numParams = 0;
2338 }
2339
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002340 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2341 {
Jamie Madill437fa652016-05-03 15:13:24 -04002342 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002343 return false;
2344 }
2345
2346 switch (pname)
2347 {
2348 case GL_CURRENT_QUERY_EXT:
2349 if (target == GL_TIMESTAMP_EXT)
2350 {
Jamie Madill437fa652016-05-03 15:13:24 -04002351 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002352 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2353 return false;
2354 }
2355 break;
2356 case GL_QUERY_COUNTER_BITS_EXT:
2357 if (!context->getExtensions().disjointTimerQuery ||
2358 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2359 {
Jamie Madill437fa652016-05-03 15:13:24 -04002360 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002361 return false;
2362 }
2363 break;
2364 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002365 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002366 return false;
2367 }
2368
Geoff Lang2186c382016-10-14 10:54:54 -04002369 if (numParams)
2370 {
2371 // All queries return only one value
2372 *numParams = 1;
2373 }
2374
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002375 return true;
2376}
2377
2378bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2379{
2380 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002381 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002382 {
Jamie Madill437fa652016-05-03 15:13:24 -04002383 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002384 return false;
2385 }
2386
Geoff Lang2186c382016-10-14 10:54:54 -04002387 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002388}
2389
Geoff Lang2186c382016-10-14 10:54:54 -04002390bool ValidateGetQueryivRobustANGLE(Context *context,
2391 GLenum target,
2392 GLenum pname,
2393 GLsizei bufSize,
2394 GLsizei *length,
2395 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002396{
Geoff Lang2186c382016-10-14 10:54:54 -04002397 if (!ValidateRobustEntryPoint(context, bufSize))
2398 {
2399 return false;
2400 }
2401
2402 if (!ValidateGetQueryivBase(context, target, pname, length))
2403 {
2404 return false;
2405 }
2406
2407 if (!ValidateRobustBufferSize(context, bufSize, *length))
2408 {
2409 return false;
2410 }
2411
2412 return true;
2413}
2414
2415bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2416{
2417 if (numParams)
2418 {
2419 *numParams = 0;
2420 }
2421
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002422 Query *queryObject = context->getQuery(id, false, GL_NONE);
2423
2424 if (!queryObject)
2425 {
Jamie Madill437fa652016-05-03 15:13:24 -04002426 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002427 return false;
2428 }
2429
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002430 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002431 {
Jamie Madill437fa652016-05-03 15:13:24 -04002432 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002433 return false;
2434 }
2435
2436 switch (pname)
2437 {
2438 case GL_QUERY_RESULT_EXT:
2439 case GL_QUERY_RESULT_AVAILABLE_EXT:
2440 break;
2441
2442 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002443 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002444 return false;
2445 }
2446
Geoff Lang2186c382016-10-14 10:54:54 -04002447 if (numParams)
2448 {
2449 *numParams = 1;
2450 }
2451
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002452 return true;
2453}
2454
2455bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2456{
2457 if (!context->getExtensions().disjointTimerQuery)
2458 {
Jamie Madill437fa652016-05-03 15:13:24 -04002459 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002460 return false;
2461 }
Geoff Lang2186c382016-10-14 10:54:54 -04002462 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2463}
2464
2465bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2466 GLuint id,
2467 GLenum pname,
2468 GLsizei bufSize,
2469 GLsizei *length,
2470 GLint *params)
2471{
2472 if (!context->getExtensions().disjointTimerQuery)
2473 {
2474 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2475 return false;
2476 }
2477
2478 if (!ValidateRobustEntryPoint(context, bufSize))
2479 {
2480 return false;
2481 }
2482
2483 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2484 {
2485 return false;
2486 }
2487
2488 if (!ValidateRobustBufferSize(context, bufSize, *length))
2489 {
2490 return false;
2491 }
2492
2493 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002494}
2495
2496bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2497{
2498 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002499 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002500 {
Jamie Madill437fa652016-05-03 15:13:24 -04002501 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002502 return false;
2503 }
Geoff Lang2186c382016-10-14 10:54:54 -04002504 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2505}
2506
2507bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2508 GLuint id,
2509 GLenum pname,
2510 GLsizei bufSize,
2511 GLsizei *length,
2512 GLuint *params)
2513{
2514 if (!context->getExtensions().disjointTimerQuery &&
2515 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2516 {
2517 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2518 return false;
2519 }
2520
2521 if (!ValidateRobustEntryPoint(context, bufSize))
2522 {
2523 return false;
2524 }
2525
2526 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2527 {
2528 return false;
2529 }
2530
2531 if (!ValidateRobustBufferSize(context, bufSize, *length))
2532 {
2533 return false;
2534 }
2535
2536 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002537}
2538
2539bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2540{
2541 if (!context->getExtensions().disjointTimerQuery)
2542 {
Jamie Madill437fa652016-05-03 15:13:24 -04002543 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002544 return false;
2545 }
Geoff Lang2186c382016-10-14 10:54:54 -04002546 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2547}
2548
2549bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2550 GLuint id,
2551 GLenum pname,
2552 GLsizei bufSize,
2553 GLsizei *length,
2554 GLint64 *params)
2555{
2556 if (!context->getExtensions().disjointTimerQuery)
2557 {
2558 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2559 return false;
2560 }
2561
2562 if (!ValidateRobustEntryPoint(context, bufSize))
2563 {
2564 return false;
2565 }
2566
2567 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2568 {
2569 return false;
2570 }
2571
2572 if (!ValidateRobustBufferSize(context, bufSize, *length))
2573 {
2574 return false;
2575 }
2576
2577 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002578}
2579
2580bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2581{
2582 if (!context->getExtensions().disjointTimerQuery)
2583 {
Jamie Madill437fa652016-05-03 15:13:24 -04002584 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002585 return false;
2586 }
Geoff Lang2186c382016-10-14 10:54:54 -04002587 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2588}
2589
2590bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2591 GLuint id,
2592 GLenum pname,
2593 GLsizei bufSize,
2594 GLsizei *length,
2595 GLuint64 *params)
2596{
2597 if (!context->getExtensions().disjointTimerQuery)
2598 {
2599 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2600 return false;
2601 }
2602
2603 if (!ValidateRobustEntryPoint(context, bufSize))
2604 {
2605 return false;
2606 }
2607
2608 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2609 {
2610 return false;
2611 }
2612
2613 if (!ValidateRobustBufferSize(context, bufSize, *length))
2614 {
2615 return false;
2616 }
2617
2618 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002619}
2620
Jamie Madill62d31cb2015-09-11 13:25:51 -04002621static bool ValidateUniformCommonBase(gl::Context *context,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002622 gl::Program *program,
Jamie Madill62d31cb2015-09-11 13:25:51 -04002623 GLenum targetUniformType,
2624 GLint location,
2625 GLsizei count,
2626 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002627{
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002628 // TODO(Jiajia): Add image uniform check in future.
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002629 if (count < 0)
2630 {
Jamie Madill437fa652016-05-03 15:13:24 -04002631 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002632 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002633 }
2634
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002635 if (!program || !program->isLinked())
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002636 {
Jamie Madill437fa652016-05-03 15:13:24 -04002637 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002638 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002639 }
2640
Geoff Langd8605522016-04-13 10:19:12 -04002641 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002642 {
2643 // Silently ignore the uniform command
2644 return false;
2645 }
2646
Geoff Lang7dd2e102014-11-10 15:19:26 -05002647 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002648 {
Jamie Madill437fa652016-05-03 15:13:24 -04002649 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002650 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002651 }
2652
Jamie Madill62d31cb2015-09-11 13:25:51 -04002653 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002654
2655 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002656 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002657 {
Jamie Madill437fa652016-05-03 15:13:24 -04002658 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002659 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002660 }
2661
Jamie Madill62d31cb2015-09-11 13:25:51 -04002662 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002663 return true;
2664}
2665
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002666bool ValidateProgramUniform(gl::Context *context,
2667 GLenum uniformType,
2668 GLuint program,
2669 GLint location,
2670 GLsizei count)
2671{
2672 // Check for ES31 program uniform entry points
2673 if (context->getClientVersion() < Version(3, 1))
2674 {
2675 context->handleError(Error(GL_INVALID_OPERATION));
2676 return false;
2677 }
2678
2679 const LinkedUniform *uniform = nullptr;
2680 gl::Program *programObject = GetValidProgram(context, program);
2681 if (!ValidateUniformCommonBase(context, programObject, uniformType, location, count, &uniform))
2682 {
2683 return false;
2684 }
2685
2686 GLenum targetBoolType = VariableBoolVectorType(uniformType);
2687 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
2688 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2689 {
2690 context->handleError(Error(GL_INVALID_OPERATION));
2691 return false;
2692 }
2693
2694 return true;
2695}
2696
2697bool ValidateProgramUniformMatrix(gl::Context *context,
2698 GLenum matrixType,
2699 GLuint program,
2700 GLint location,
2701 GLsizei count,
2702 GLboolean transpose)
2703{
2704 // Check for ES31 program uniform entry points
2705 if (context->getClientVersion() < Version(3, 1))
2706 {
2707 context->handleError(Error(GL_INVALID_OPERATION));
2708 return false;
2709 }
2710
2711 const LinkedUniform *uniform = nullptr;
2712 gl::Program *programObject = GetValidProgram(context, program);
2713 if (!ValidateUniformCommonBase(context, programObject, matrixType, location, count, &uniform))
2714 {
2715 return false;
2716 }
2717
2718 if (uniform->type != matrixType)
2719 {
2720 context->handleError(Error(GL_INVALID_OPERATION));
2721 return false;
2722 }
2723
2724 return true;
2725}
2726
Jamie Madillaa981bd2014-05-20 10:55:55 -04002727bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2728{
2729 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002730 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2731 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002732 {
Jamie Madill437fa652016-05-03 15:13:24 -04002733 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002734 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002735 }
2736
Jamie Madill62d31cb2015-09-11 13:25:51 -04002737 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002738 gl::Program *program = context->getGLState().getProgram();
2739 if (!ValidateUniformCommonBase(context, program, uniformType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002740 {
2741 return false;
2742 }
2743
He Yunchaoced53ae2016-11-29 15:00:51 +08002744 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002745 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002746 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2747 {
Jamie Madill437fa652016-05-03 15:13:24 -04002748 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002749 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002750 }
2751
2752 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002753}
2754
He Yunchaoced53ae2016-11-29 15:00:51 +08002755bool ValidateUniformMatrix(gl::Context *context,
2756 GLenum matrixType,
2757 GLint location,
2758 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002759 GLboolean transpose)
2760{
2761 // Check for ES3 uniform entry points
2762 int rows = VariableRowCount(matrixType);
2763 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002764 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002765 {
Jamie Madill437fa652016-05-03 15:13:24 -04002766 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002767 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002768 }
2769
Martin Radev1be913c2016-07-11 17:59:16 +03002770 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002771 {
Jamie Madill437fa652016-05-03 15:13:24 -04002772 context->handleError(Error(GL_INVALID_VALUE));
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, matrixType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002779 {
2780 return false;
2781 }
2782
2783 if (uniform->type != matrixType)
2784 {
Jamie Madill437fa652016-05-03 15:13:24 -04002785 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002786 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002787 }
2788
2789 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002790}
2791
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002792bool ValidateStateQuery(ValidationContext *context,
2793 GLenum pname,
2794 GLenum *nativeType,
2795 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002796{
2797 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2798 {
Jamie Madill437fa652016-05-03 15:13:24 -04002799 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002800 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002801 }
2802
Jamie Madill0af26e12015-03-05 19:54:33 -05002803 const Caps &caps = context->getCaps();
2804
Jamie Madill893ab082014-05-16 16:56:10 -04002805 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2806 {
2807 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2808
Jamie Madill0af26e12015-03-05 19:54:33 -05002809 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002810 {
Jamie Madill437fa652016-05-03 15:13:24 -04002811 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002812 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002813 }
2814 }
2815
2816 switch (pname)
2817 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002818 case GL_TEXTURE_BINDING_2D:
2819 case GL_TEXTURE_BINDING_CUBE_MAP:
2820 case GL_TEXTURE_BINDING_3D:
2821 case GL_TEXTURE_BINDING_2D_ARRAY:
2822 break;
2823 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2824 if (!context->getExtensions().eglStreamConsumerExternal &&
2825 !context->getExtensions().eglImageExternal)
2826 {
2827 context->handleError(Error(GL_INVALID_ENUM,
2828 "Neither NV_EGL_stream_consumer_external nor "
2829 "GL_OES_EGL_image_external extensions enabled"));
2830 return false;
2831 }
2832 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002833
He Yunchaoced53ae2016-11-29 15:00:51 +08002834 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2835 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002836 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002837 if (context->getGLState().getReadFramebuffer()->checkStatus(
2838 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002839 {
Jamie Madill437fa652016-05-03 15:13:24 -04002840 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002841 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002842 }
2843
Jamie Madill51f40ec2016-06-15 14:06:00 -04002844 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2845 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002846
2847 if (framebuffer->getReadBufferState() == GL_NONE)
2848 {
2849 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2850 return false;
2851 }
2852
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002853 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002854 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002855 {
Jamie Madill437fa652016-05-03 15:13:24 -04002856 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002857 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002858 }
2859 }
2860 break;
2861
He Yunchaoced53ae2016-11-29 15:00:51 +08002862 default:
2863 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002864 }
2865
2866 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002867 if (*numParams == 0)
2868 {
2869 return false;
2870 }
2871
2872 return true;
2873}
2874
2875bool ValidateRobustStateQuery(ValidationContext *context,
2876 GLenum pname,
2877 GLsizei bufSize,
2878 GLenum *nativeType,
2879 unsigned int *numParams)
2880{
2881 if (!ValidateRobustEntryPoint(context, bufSize))
2882 {
2883 return false;
2884 }
2885
2886 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2887 {
2888 return false;
2889 }
2890
2891 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002892 {
2893 return false;
2894 }
2895
2896 return true;
2897}
2898
Jamie Madillc29968b2016-01-20 11:17:23 -05002899bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2900 GLenum target,
2901 GLint level,
2902 GLenum internalformat,
2903 bool isSubImage,
2904 GLint xoffset,
2905 GLint yoffset,
2906 GLint zoffset,
2907 GLint x,
2908 GLint y,
2909 GLsizei width,
2910 GLsizei height,
2911 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002912 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002913{
Jamie Madill560a8d82014-05-21 13:06:20 -04002914 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2915 {
Jamie Madill437fa652016-05-03 15:13:24 -04002916 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002917 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002918 }
2919
He Yunchaoced53ae2016-11-29 15:00:51 +08002920 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2921 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002922 {
Jamie Madill437fa652016-05-03 15:13:24 -04002923 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002924 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002925 }
2926
2927 if (border != 0)
2928 {
Jamie Madill437fa652016-05-03 15:13:24 -04002929 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002930 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002931 }
2932
2933 if (!ValidMipLevel(context, target, level))
2934 {
Jamie Madill437fa652016-05-03 15:13:24 -04002935 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002936 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002937 }
2938
Jamie Madill51f40ec2016-06-15 14:06:00 -04002939 const auto &state = context->getGLState();
2940 auto readFramebuffer = state.getReadFramebuffer();
2941 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002942 {
Jamie Madill437fa652016-05-03 15:13:24 -04002943 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002944 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002945 }
2946
Jamie Madill51f40ec2016-06-15 14:06:00 -04002947 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002948 {
Jamie Madill437fa652016-05-03 15:13:24 -04002949 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002950 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002951 }
2952
Martin Radev138064f2016-07-15 12:03:41 +03002953 if (readFramebuffer->getReadBufferState() == GL_NONE)
2954 {
2955 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2956 return false;
2957 }
2958
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002959 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2960 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
2961 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
2962 // situation is an application error that would lead to a crash in ANGLE.
2963 if (readFramebuffer->getReadColorbuffer() == nullptr)
2964 {
2965 context->handleError(Error(GL_INVALID_OPERATION, "Missing read attachment"));
2966 return false;
2967 }
2968
Geoff Langaae65a42014-05-26 12:43:44 -04002969 const gl::Caps &caps = context->getCaps();
2970
Geoff Langaae65a42014-05-26 12:43:44 -04002971 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002972 switch (target)
2973 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002974 case GL_TEXTURE_2D:
2975 maxDimension = caps.max2DTextureSize;
2976 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002977
He Yunchaoced53ae2016-11-29 15:00:51 +08002978 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2979 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2980 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2981 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2982 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2983 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2984 maxDimension = caps.maxCubeMapTextureSize;
2985 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002986
He Yunchaoced53ae2016-11-29 15:00:51 +08002987 case GL_TEXTURE_2D_ARRAY:
2988 maxDimension = caps.max2DTextureSize;
2989 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002990
He Yunchaoced53ae2016-11-29 15:00:51 +08002991 case GL_TEXTURE_3D:
2992 maxDimension = caps.max3DTextureSize;
2993 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002994
He Yunchaoced53ae2016-11-29 15:00:51 +08002995 default:
2996 context->handleError(Error(GL_INVALID_ENUM));
2997 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002998 }
2999
Jamie Madillc29968b2016-01-20 11:17:23 -05003000 gl::Texture *texture =
3001 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04003002 if (!texture)
3003 {
Jamie Madill437fa652016-05-03 15:13:24 -04003004 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003005 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003006 }
3007
Geoff Lang69cce582015-09-17 13:20:36 -04003008 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04003009 {
Jamie Madill437fa652016-05-03 15:13:24 -04003010 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003011 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003012 }
3013
Geoff Lang5d601382014-07-22 15:14:06 -04003014 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3015
3016 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003017 {
Jamie Madill437fa652016-05-03 15:13:24 -04003018 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003019 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003020 }
3021
Geoff Langa9be0dc2014-12-17 12:34:40 -05003022 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003023 {
Jamie Madill437fa652016-05-03 15:13:24 -04003024 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003025 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003026 }
3027
3028 if (isSubImage)
3029 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003030 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3031 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3032 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003033 {
Jamie Madill437fa652016-05-03 15:13:24 -04003034 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003035 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003036 }
3037 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003038 else
3039 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003040 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003041 {
Jamie Madill437fa652016-05-03 15:13:24 -04003042 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003043 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003044 }
3045
Geoff Langeb66a6e2016-10-31 13:06:12 -04003046 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003047 {
Jamie Madill437fa652016-05-03 15:13:24 -04003048 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003049 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003050 }
3051
3052 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003053 if (static_cast<int>(width) > maxLevelDimension ||
3054 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003055 {
Jamie Madill437fa652016-05-03 15:13:24 -04003056 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003057 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003058 }
3059 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003060
Jamie Madill0c8abca2016-07-22 20:21:26 -04003061 if (textureFormatOut)
3062 {
3063 *textureFormatOut = texture->getFormat(target, level);
3064 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003065 return true;
3066}
3067
Jiajia Qind9671222016-11-29 16:30:31 +08003068bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04003069{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003070 switch (mode)
3071 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003072 case GL_POINTS:
3073 case GL_LINES:
3074 case GL_LINE_LOOP:
3075 case GL_LINE_STRIP:
3076 case GL_TRIANGLES:
3077 case GL_TRIANGLE_STRIP:
3078 case GL_TRIANGLE_FAN:
3079 break;
3080 default:
3081 context->handleError(Error(GL_INVALID_ENUM));
3082 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003083 }
3084
Jamie Madill250d33f2014-06-06 17:09:03 -04003085 if (count < 0)
3086 {
Jamie Madill437fa652016-05-03 15:13:24 -04003087 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003088 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003089 }
3090
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003091 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003092
Jamie Madill250d33f2014-06-06 17:09:03 -04003093 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003094 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003095 {
Jamie Madill437fa652016-05-03 15:13:24 -04003096 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003097 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003098 }
3099
Jamie Madill51f40ec2016-06-15 14:06:00 -04003100 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04003101 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04003102 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04003103 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
He Yunchaoced53ae2016-11-29 15:00:51 +08003104 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
3105 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003106 const DepthStencilState &depthStencilState = state.getDepthStencilState();
3107 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3108 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04003109 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04003110 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3111 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04003112 {
3113 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3114 // Section 6.10 of the WebGL 1.0 spec
He Yunchaoced53ae2016-11-29 15:00:51 +08003115 ERR("This ANGLE implementation does not support separate front/back stencil "
Geoff Lang3a86ad32015-09-01 11:47:05 -04003116 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04003117 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003118 return false;
3119 }
Jamie Madillac528012014-06-20 13:21:23 -04003120 }
3121
Jamie Madill51f40ec2016-06-15 14:06:00 -04003122 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003123 {
Jamie Madill437fa652016-05-03 15:13:24 -04003124 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003125 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003126 }
3127
Geoff Lang7dd2e102014-11-10 15:19:26 -05003128 gl::Program *program = state.getProgram();
3129 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003130 {
Jamie Madill437fa652016-05-03 15:13:24 -04003131 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003132 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003133 }
3134
Geoff Lang7dd2e102014-11-10 15:19:26 -05003135 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003136 {
Jamie Madill437fa652016-05-03 15:13:24 -04003137 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003138 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003139 }
3140
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003141 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003142 for (unsigned int uniformBlockIndex = 0;
3143 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003144 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003145 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003146 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003147 const OffsetBindingPointer<Buffer> &uniformBuffer =
3148 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003149
Geoff Lang5d124a62015-09-15 13:03:27 -04003150 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003151 {
3152 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003153 context->handleError(
3154 Error(GL_INVALID_OPERATION,
3155 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003156 return false;
3157 }
3158
Geoff Lang5d124a62015-09-15 13:03:27 -04003159 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003160 if (uniformBufferSize == 0)
3161 {
3162 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003163 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003164 }
3165
Jamie Madill62d31cb2015-09-11 13:25:51 -04003166 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003167 {
3168 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003169 context->handleError(
3170 Error(GL_INVALID_OPERATION,
3171 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003172 return false;
3173 }
3174 }
3175
Jamie Madill250d33f2014-06-06 17:09:03 -04003176 // No-op if zero count
3177 return (count > 0);
3178}
3179
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003180bool ValidateDrawArrays(ValidationContext *context,
3181 GLenum mode,
3182 GLint first,
3183 GLsizei count,
3184 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003185{
Jamie Madillfd716582014-06-06 17:09:04 -04003186 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003187 {
Jamie Madill437fa652016-05-03 15:13:24 -04003188 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003189 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003190 }
3191
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003192 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003193 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003194 if (curTransformFeedback && curTransformFeedback->isActive() &&
3195 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003196 {
3197 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003198 // that does not match the current transform feedback object's draw mode (if transform
3199 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003200 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003201 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003202 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003203 }
3204
Jiajia Qind9671222016-11-29 16:30:31 +08003205 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003206 {
3207 return false;
3208 }
3209
Corentin Wallez92db6942016-12-09 13:10:36 -05003210 CheckedNumeric<GLint> maxVertex = first;
3211 maxVertex += count;
3212 maxVertex -= 1;
3213
3214 if (!maxVertex.IsValid())
3215 {
3216 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3217 return false;
3218 }
3219
3220 if (!ValidateDrawAttribs(context, primcount, maxVertex.ValueOrDie(), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003221 {
3222 return false;
3223 }
3224
3225 return true;
3226}
3227
He Yunchaoced53ae2016-11-29 15:00:51 +08003228bool ValidateDrawArraysInstanced(Context *context,
3229 GLenum mode,
3230 GLint first,
3231 GLsizei count,
3232 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003233{
3234 if (primcount < 0)
3235 {
Jamie Madill437fa652016-05-03 15:13:24 -04003236 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003237 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003238 }
3239
Jamie Madill2b976812014-08-25 15:47:49 -04003240 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003241 {
3242 return false;
3243 }
3244
3245 // No-op if zero primitive count
3246 return (primcount > 0);
3247}
3248
Geoff Lang87a93302014-09-16 13:29:43 -04003249static bool ValidateDrawInstancedANGLE(Context *context)
3250{
3251 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003252 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003253
Geoff Lang7dd2e102014-11-10 15:19:26 -05003254 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003255
3256 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003257 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003258 {
3259 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003260 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003261 {
3262 return true;
3263 }
3264 }
3265
Jamie Madill437fa652016-05-03 15:13:24 -04003266 context->handleError(Error(GL_INVALID_OPERATION,
3267 "ANGLE_instanced_arrays requires that at least one active attribute"
3268 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003269 return false;
3270}
3271
He Yunchaoced53ae2016-11-29 15:00:51 +08003272bool ValidateDrawArraysInstancedANGLE(Context *context,
3273 GLenum mode,
3274 GLint first,
3275 GLsizei count,
3276 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003277{
3278 if (!ValidateDrawInstancedANGLE(context))
3279 {
3280 return false;
3281 }
3282
3283 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3284}
3285
Jiajia Qind9671222016-11-29 16:30:31 +08003286bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003287{
Jamie Madill250d33f2014-06-06 17:09:03 -04003288 switch (type)
3289 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003290 case GL_UNSIGNED_BYTE:
3291 case GL_UNSIGNED_SHORT:
3292 break;
3293 case GL_UNSIGNED_INT:
3294 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3295 {
3296 context->handleError(Error(GL_INVALID_ENUM));
3297 return false;
3298 }
3299 break;
3300 default:
3301 context->handleError(Error(GL_INVALID_ENUM));
3302 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003303 }
3304
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003305 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003306
3307 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003308 if (curTransformFeedback && curTransformFeedback->isActive() &&
3309 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003310 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003311 // It is an invalid operation to call DrawElements, DrawRangeElements or
3312 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003313 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003314 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003315 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003316 }
3317
Jiajia Qind9671222016-11-29 16:30:31 +08003318 return true;
3319}
3320
3321bool ValidateDrawElements(ValidationContext *context,
3322 GLenum mode,
3323 GLsizei count,
3324 GLenum type,
3325 const GLvoid *indices,
3326 GLsizei primcount,
3327 IndexRange *indexRangeOut)
3328{
3329 if (!ValidateDrawElementsBase(context, type))
3330 return false;
3331
3332 const State &state = context->getGLState();
3333
Jamie Madill250d33f2014-06-06 17:09:03 -04003334 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003335 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003336 {
Jamie Madill437fa652016-05-03 15:13:24 -04003337 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003338 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003339 }
3340
He Yunchaoced53ae2016-11-29 15:00:51 +08003341 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003342 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003343
Jamie Madillae3000b2014-08-25 15:47:51 -04003344 if (elementArrayBuffer)
3345 {
3346 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3347
3348 GLint64 offset = reinterpret_cast<GLint64>(indices);
He Yunchaoced53ae2016-11-29 15:00:51 +08003349 GLint64 byteCount =
3350 static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count) + offset;
Jamie Madillae3000b2014-08-25 15:47:51 -04003351
3352 // check for integer overflows
3353 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3354 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3355 {
Jamie Madill437fa652016-05-03 15:13:24 -04003356 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003357 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003358 }
3359
3360 // Check for reading past the end of the bound buffer object
3361 if (byteCount > elementArrayBuffer->getSize())
3362 {
Jamie Madill437fa652016-05-03 15:13:24 -04003363 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003364 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003365 }
3366 }
Corentin Wallez327411e2016-12-09 11:09:17 -05003367 else if (context->getExtensions().webglCompatibility && count > 0)
3368 {
3369 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3370 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3371 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3372 context->handleError(
3373 Error(GL_INVALID_OPERATION, "There is no element array buffer bound and count > 0."));
3374 return false;
3375 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003376 else if (!indices)
3377 {
Corentin Wallez327411e2016-12-09 11:09:17 -05003378 // This is an application error that would normally result in a crash,
3379 // but we catch it and return an error
3380 context->handleError(
3381 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003382 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003383 }
3384
Jiajia Qind9671222016-11-29 16:30:31 +08003385 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003386 {
3387 return false;
3388 }
3389
Jamie Madill2b976812014-08-25 15:47:49 -04003390 // Use max index to validate if our vertex buffers are large enough for the pull.
3391 // TODO: offer fast path, with disabled index validation.
3392 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3393 if (elementArrayBuffer)
3394 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003395 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003396 Error error =
3397 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3398 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003399 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003400 {
Jamie Madill437fa652016-05-03 15:13:24 -04003401 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003402 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003403 }
3404 }
3405 else
3406 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003407 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003408 }
3409
Jamie Madille79b1e12015-11-04 16:36:37 -05003410 // If we use an index greater than our maximum supported index range, return an error.
3411 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3412 // return an error if possible here.
3413 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3414 {
Jamie Madill437fa652016-05-03 15:13:24 -04003415 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003416 return false;
3417 }
3418
Corentin Wallez92db6942016-12-09 13:10:36 -05003419 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3420 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003421 {
3422 return false;
3423 }
3424
Geoff Lang3edfe032015-09-04 16:38:24 -04003425 // No op if there are no real indices in the index data (all are primitive restart).
3426 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003427}
3428
Geoff Langb1196682014-07-23 13:47:29 -04003429bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003430 GLenum mode,
3431 GLsizei count,
3432 GLenum type,
3433 const GLvoid *indices,
3434 GLsizei primcount,
3435 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003436{
3437 if (primcount < 0)
3438 {
Jamie Madill437fa652016-05-03 15:13:24 -04003439 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003440 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003441 }
3442
Jamie Madill2b976812014-08-25 15:47:49 -04003443 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003444 {
3445 return false;
3446 }
3447
3448 // No-op zero primitive count
3449 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003450}
3451
Geoff Lang3edfe032015-09-04 16:38:24 -04003452bool ValidateDrawElementsInstancedANGLE(Context *context,
3453 GLenum mode,
3454 GLsizei count,
3455 GLenum type,
3456 const GLvoid *indices,
3457 GLsizei primcount,
3458 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003459{
3460 if (!ValidateDrawInstancedANGLE(context))
3461 {
3462 return false;
3463 }
3464
He Yunchaoced53ae2016-11-29 15:00:51 +08003465 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3466 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003467}
3468
He Yunchaoced53ae2016-11-29 15:00:51 +08003469bool ValidateFramebufferTextureBase(Context *context,
3470 GLenum target,
3471 GLenum attachment,
3472 GLuint texture,
3473 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003474{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003475 if (!ValidFramebufferTarget(target))
3476 {
Jamie Madill437fa652016-05-03 15:13:24 -04003477 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003478 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003479 }
3480
3481 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003482 {
3483 return false;
3484 }
3485
Jamie Madill55ec3b12014-07-03 10:38:57 -04003486 if (texture != 0)
3487 {
3488 gl::Texture *tex = context->getTexture(texture);
3489
3490 if (tex == NULL)
3491 {
Jamie Madill437fa652016-05-03 15:13:24 -04003492 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003493 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003494 }
3495
3496 if (level < 0)
3497 {
Jamie Madill437fa652016-05-03 15:13:24 -04003498 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003499 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003500 }
3501 }
3502
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003503 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003504 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003505
Jamie Madill84115c92015-04-23 15:00:07 -04003506 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003507 {
Jamie Madill437fa652016-05-03 15:13:24 -04003508 context->handleError(
3509 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003510 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003511 }
3512
3513 return true;
3514}
3515
He Yunchaoced53ae2016-11-29 15:00:51 +08003516bool ValidateFramebufferTexture2D(Context *context,
3517 GLenum target,
3518 GLenum attachment,
3519 GLenum textarget,
3520 GLuint texture,
3521 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003522{
He Yunchaoced53ae2016-11-29 15:00:51 +08003523 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3524 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003525 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3526 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003527 {
Jamie Madill437fa652016-05-03 15:13:24 -04003528 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003529 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003530 }
3531
3532 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003533 {
3534 return false;
3535 }
3536
Jamie Madill55ec3b12014-07-03 10:38:57 -04003537 if (texture != 0)
3538 {
3539 gl::Texture *tex = context->getTexture(texture);
3540 ASSERT(tex);
3541
Jamie Madill2a6564e2014-07-11 09:53:19 -04003542 const gl::Caps &caps = context->getCaps();
3543
Jamie Madill55ec3b12014-07-03 10:38:57 -04003544 switch (textarget)
3545 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003546 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003547 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003548 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003549 {
Jamie Madill437fa652016-05-03 15:13:24 -04003550 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003551 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003552 }
3553 if (tex->getTarget() != GL_TEXTURE_2D)
3554 {
Jamie Madill437fa652016-05-03 15:13:24 -04003555 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003556 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003557 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003558 }
3559 break;
3560
He Yunchaoced53ae2016-11-29 15:00:51 +08003561 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3562 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3563 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3564 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3565 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3566 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003567 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003568 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003569 {
Jamie Madill437fa652016-05-03 15:13:24 -04003570 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003571 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003572 }
3573 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3574 {
Jamie Madill437fa652016-05-03 15:13:24 -04003575 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003576 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003577 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003578 }
3579 break;
3580
He Yunchaoced53ae2016-11-29 15:00:51 +08003581 default:
3582 context->handleError(Error(GL_INVALID_ENUM));
3583 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003584 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003585
Jamie Madilla3944d42016-07-22 22:13:26 -04003586 const Format &format = tex->getFormat(textarget, level);
3587 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003588 {
Jamie Madill437fa652016-05-03 15:13:24 -04003589 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003590 return false;
3591 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003592 }
3593
Jamie Madill570f7c82014-07-03 10:38:54 -04003594 return true;
3595}
3596
Geoff Langb1196682014-07-23 13:47:29 -04003597bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003598{
3599 if (program == 0)
3600 {
Jamie Madill437fa652016-05-03 15:13:24 -04003601 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003602 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003603 }
3604
Dian Xiang769769a2015-09-09 15:20:08 -07003605 gl::Program *programObject = GetValidProgram(context, program);
3606 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003607 {
3608 return false;
3609 }
3610
Jamie Madill0063c512014-08-25 15:47:53 -04003611 if (!programObject || !programObject->isLinked())
3612 {
Jamie Madill437fa652016-05-03 15:13:24 -04003613 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003614 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003615 }
3616
Geoff Lang7dd2e102014-11-10 15:19:26 -05003617 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003618 {
Jamie Madill437fa652016-05-03 15:13:24 -04003619 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003620 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003621 }
3622
Jamie Madill0063c512014-08-25 15:47:53 -04003623 return true;
3624}
3625
He Yunchaoced53ae2016-11-29 15:00:51 +08003626bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003627{
3628 return ValidateGetUniformBase(context, program, location);
3629}
3630
He Yunchaoced53ae2016-11-29 15:00:51 +08003631bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003632{
Jamie Madill78f41802014-08-25 15:47:55 -04003633 return ValidateGetUniformBase(context, program, location);
3634}
3635
Geoff Langf41d0ee2016-10-07 13:04:23 -04003636static bool ValidateSizedGetUniform(Context *context,
3637 GLuint program,
3638 GLint location,
3639 GLsizei bufSize,
3640 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003641{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003642 if (length)
3643 {
3644 *length = 0;
3645 }
3646
Jamie Madill78f41802014-08-25 15:47:55 -04003647 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003648 {
Jamie Madill78f41802014-08-25 15:47:55 -04003649 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003650 }
3651
Geoff Langf41d0ee2016-10-07 13:04:23 -04003652 if (bufSize < 0)
3653 {
3654 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3655 return false;
3656 }
3657
Jamie Madilla502c742014-08-28 17:19:13 -04003658 gl::Program *programObject = context->getProgram(program);
3659 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003660
Jamie Madill78f41802014-08-25 15:47:55 -04003661 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003662 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003663 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003664 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003665 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003666 context->handleError(
3667 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003668 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003669 }
3670
Geoff Langf41d0ee2016-10-07 13:04:23 -04003671 if (length)
3672 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003673 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003674 }
3675
Jamie Madill0063c512014-08-25 15:47:53 -04003676 return true;
3677}
3678
He Yunchaoced53ae2016-11-29 15:00:51 +08003679bool ValidateGetnUniformfvEXT(Context *context,
3680 GLuint program,
3681 GLint location,
3682 GLsizei bufSize,
3683 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003684{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003685 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003686}
3687
He Yunchaoced53ae2016-11-29 15:00:51 +08003688bool ValidateGetnUniformivEXT(Context *context,
3689 GLuint program,
3690 GLint location,
3691 GLsizei bufSize,
3692 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003693{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003694 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3695}
3696
3697bool ValidateGetUniformfvRobustANGLE(Context *context,
3698 GLuint program,
3699 GLint location,
3700 GLsizei bufSize,
3701 GLsizei *length,
3702 GLfloat *params)
3703{
3704 if (!ValidateRobustEntryPoint(context, bufSize))
3705 {
3706 return false;
3707 }
3708
3709 // bufSize is validated in ValidateSizedGetUniform
3710 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3711}
3712
3713bool ValidateGetUniformivRobustANGLE(Context *context,
3714 GLuint program,
3715 GLint location,
3716 GLsizei bufSize,
3717 GLsizei *length,
3718 GLint *params)
3719{
3720 if (!ValidateRobustEntryPoint(context, bufSize))
3721 {
3722 return false;
3723 }
3724
3725 // bufSize is validated in ValidateSizedGetUniform
3726 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3727}
3728
3729bool ValidateGetUniformuivRobustANGLE(Context *context,
3730 GLuint program,
3731 GLint location,
3732 GLsizei bufSize,
3733 GLsizei *length,
3734 GLuint *params)
3735{
3736 if (!ValidateRobustEntryPoint(context, bufSize))
3737 {
3738 return false;
3739 }
3740
3741 if (context->getClientMajorVersion() < 3)
3742 {
3743 context->handleError(
3744 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3745 return false;
3746 }
3747
3748 // bufSize is validated in ValidateSizedGetUniform
3749 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003750}
3751
He Yunchaoced53ae2016-11-29 15:00:51 +08003752bool ValidateDiscardFramebufferBase(Context *context,
3753 GLenum target,
3754 GLsizei numAttachments,
3755 const GLenum *attachments,
3756 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003757{
3758 if (numAttachments < 0)
3759 {
Jamie Madill437fa652016-05-03 15:13:24 -04003760 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003761 return false;
3762 }
3763
3764 for (GLsizei i = 0; i < numAttachments; ++i)
3765 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003766 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003767 {
3768 if (defaultFramebuffer)
3769 {
Jamie Madill437fa652016-05-03 15:13:24 -04003770 context->handleError(Error(
3771 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003772 return false;
3773 }
3774
3775 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3776 {
Jamie Madill437fa652016-05-03 15:13:24 -04003777 context->handleError(Error(GL_INVALID_OPERATION,
3778 "Requested color attachment is greater than the maximum "
3779 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003780 return false;
3781 }
3782 }
3783 else
3784 {
3785 switch (attachments[i])
3786 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003787 case GL_DEPTH_ATTACHMENT:
3788 case GL_STENCIL_ATTACHMENT:
3789 case GL_DEPTH_STENCIL_ATTACHMENT:
3790 if (defaultFramebuffer)
3791 {
3792 context->handleError(
3793 Error(GL_INVALID_ENUM,
3794 "Invalid attachment when the default framebuffer is bound"));
3795 return false;
3796 }
3797 break;
3798 case GL_COLOR:
3799 case GL_DEPTH:
3800 case GL_STENCIL:
3801 if (!defaultFramebuffer)
3802 {
3803 context->handleError(
3804 Error(GL_INVALID_ENUM,
3805 "Invalid attachment when the default framebuffer is not bound"));
3806 return false;
3807 }
3808 break;
3809 default:
3810 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003811 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003812 }
3813 }
3814 }
3815
3816 return true;
3817}
3818
Austin Kinross6ee1e782015-05-29 17:05:37 -07003819bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3820{
3821 // Note that debug marker calls must not set error state
3822
3823 if (length < 0)
3824 {
3825 return false;
3826 }
3827
3828 if (marker == nullptr)
3829 {
3830 return false;
3831 }
3832
3833 return true;
3834}
3835
3836bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3837{
3838 // Note that debug marker calls must not set error state
3839
3840 if (length < 0)
3841 {
3842 return false;
3843 }
3844
3845 if (length > 0 && marker == nullptr)
3846 {
3847 return false;
3848 }
3849
3850 return true;
3851}
3852
Geoff Langdcab33b2015-07-21 13:03:16 -04003853bool ValidateEGLImageTargetTexture2DOES(Context *context,
3854 egl::Display *display,
3855 GLenum target,
3856 egl::Image *image)
3857{
Geoff Langa8406172015-07-21 16:53:39 -04003858 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3859 {
Jamie Madill437fa652016-05-03 15:13:24 -04003860 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003861 return false;
3862 }
3863
3864 switch (target)
3865 {
3866 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003867 if (!context->getExtensions().eglImage)
3868 {
3869 context->handleError(Error(
3870 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3871 }
3872 break;
3873
3874 case GL_TEXTURE_EXTERNAL_OES:
3875 if (!context->getExtensions().eglImageExternal)
3876 {
3877 context->handleError(Error(
3878 GL_INVALID_ENUM,
3879 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3880 }
Geoff Langa8406172015-07-21 16:53:39 -04003881 break;
3882
3883 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003884 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003885 return false;
3886 }
3887
3888 if (!display->isValidImage(image))
3889 {
Jamie Madill437fa652016-05-03 15:13:24 -04003890 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003891 return false;
3892 }
3893
3894 if (image->getSamples() > 0)
3895 {
Jamie Madill437fa652016-05-03 15:13:24 -04003896 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003897 "cannot create a 2D texture from a multisampled EGL image."));
3898 return false;
3899 }
3900
Jamie Madilla3944d42016-07-22 22:13:26 -04003901 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003902 if (!textureCaps.texturable)
3903 {
Jamie Madill437fa652016-05-03 15:13:24 -04003904 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003905 "EGL image internal format is not supported as a texture."));
3906 return false;
3907 }
3908
Geoff Langdcab33b2015-07-21 13:03:16 -04003909 return true;
3910}
3911
3912bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3913 egl::Display *display,
3914 GLenum target,
3915 egl::Image *image)
3916{
Geoff Langa8406172015-07-21 16:53:39 -04003917 if (!context->getExtensions().eglImage)
3918 {
Jamie Madill437fa652016-05-03 15:13:24 -04003919 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003920 return false;
3921 }
3922
3923 switch (target)
3924 {
3925 case GL_RENDERBUFFER:
3926 break;
3927
3928 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003929 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003930 return false;
3931 }
3932
3933 if (!display->isValidImage(image))
3934 {
Jamie Madill437fa652016-05-03 15:13:24 -04003935 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003936 return false;
3937 }
3938
Jamie Madilla3944d42016-07-22 22:13:26 -04003939 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003940 if (!textureCaps.renderable)
3941 {
Jamie Madill437fa652016-05-03 15:13:24 -04003942 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003943 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3944 return false;
3945 }
3946
Geoff Langdcab33b2015-07-21 13:03:16 -04003947 return true;
3948}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003949
3950bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3951{
Geoff Lang36167ab2015-12-07 10:27:14 -05003952 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003953 {
3954 // The default VAO should always exist
3955 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003956 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003957 return false;
3958 }
3959
3960 return true;
3961}
3962
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003963bool ValidateLinkProgram(Context *context, GLuint program)
3964{
3965 if (context->hasActiveTransformFeedback(program))
3966 {
3967 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003968 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003969 "Cannot link program while program is associated with an active "
3970 "transform feedback object."));
3971 return false;
3972 }
3973 return true;
3974}
3975
Geoff Langc5629752015-12-07 16:29:04 -05003976bool ValidateProgramBinaryBase(Context *context,
3977 GLuint program,
3978 GLenum binaryFormat,
3979 const void *binary,
3980 GLint length)
3981{
3982 Program *programObject = GetValidProgram(context, program);
3983 if (programObject == nullptr)
3984 {
3985 return false;
3986 }
3987
3988 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3989 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3990 programBinaryFormats.end())
3991 {
Jamie Madill437fa652016-05-03 15:13:24 -04003992 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003993 return false;
3994 }
3995
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003996 if (context->hasActiveTransformFeedback(program))
3997 {
3998 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003999 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004000 "Cannot change program binary while program is associated with "
4001 "an active transform feedback object."));
4002 return false;
4003 }
4004
Geoff Langc5629752015-12-07 16:29:04 -05004005 return true;
4006}
4007
4008bool ValidateGetProgramBinaryBase(Context *context,
4009 GLuint program,
4010 GLsizei bufSize,
4011 GLsizei *length,
4012 GLenum *binaryFormat,
4013 void *binary)
4014{
4015 Program *programObject = GetValidProgram(context, program);
4016 if (programObject == nullptr)
4017 {
4018 return false;
4019 }
4020
4021 if (!programObject->isLinked())
4022 {
Jamie Madill437fa652016-05-03 15:13:24 -04004023 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004024 return false;
4025 }
4026
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004027 if (context->getCaps().programBinaryFormats.empty())
4028 {
4029 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4030 return false;
4031 }
4032
Geoff Langc5629752015-12-07 16:29:04 -05004033 return true;
4034}
Jamie Madillc29968b2016-01-20 11:17:23 -05004035
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004036bool ValidateUseProgram(Context *context, GLuint program)
4037{
4038 if (program != 0)
4039 {
4040 Program *programObject = context->getProgram(program);
4041 if (!programObject)
4042 {
4043 // ES 3.1.0 section 7.3 page 72
4044 if (context->getShader(program))
4045 {
Jamie Madill437fa652016-05-03 15:13:24 -04004046 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004047 Error(GL_INVALID_OPERATION,
4048 "Attempted to use a single shader instead of a shader program."));
4049 return false;
4050 }
4051 else
4052 {
Jamie Madill437fa652016-05-03 15:13:24 -04004053 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004054 return false;
4055 }
4056 }
4057 if (!programObject->isLinked())
4058 {
Jamie Madill437fa652016-05-03 15:13:24 -04004059 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004060 return false;
4061 }
4062 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004063 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004064 {
4065 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004066 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004067 Error(GL_INVALID_OPERATION,
4068 "Cannot change active program while transform feedback is unpaused."));
4069 return false;
4070 }
4071
4072 return true;
4073}
4074
Jamie Madillc29968b2016-01-20 11:17:23 -05004075bool ValidateCopyTexImage2D(ValidationContext *context,
4076 GLenum target,
4077 GLint level,
4078 GLenum internalformat,
4079 GLint x,
4080 GLint y,
4081 GLsizei width,
4082 GLsizei height,
4083 GLint border)
4084{
Martin Radev1be913c2016-07-11 17:59:16 +03004085 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004086 {
4087 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4088 0, x, y, width, height, border);
4089 }
4090
Martin Radev1be913c2016-07-11 17:59:16 +03004091 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004092 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4093 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004094}
Jamie Madillc29968b2016-01-20 11:17:23 -05004095
4096bool ValidateFramebufferRenderbuffer(Context *context,
4097 GLenum target,
4098 GLenum attachment,
4099 GLenum renderbuffertarget,
4100 GLuint renderbuffer)
4101{
4102 if (!ValidFramebufferTarget(target) ||
4103 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4104 {
Jamie Madill437fa652016-05-03 15:13:24 -04004105 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004106 return false;
4107 }
4108
4109 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4110 renderbuffertarget, renderbuffer);
4111}
4112
4113bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4114{
4115 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4116 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4117 {
Jamie Madill437fa652016-05-03 15:13:24 -04004118 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004119 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4120 return false;
4121 }
4122
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004123 ASSERT(context->getGLState().getDrawFramebuffer());
4124 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004125 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4126
4127 // This should come first before the check for the default frame buffer
4128 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4129 // rather than INVALID_OPERATION
4130 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4131 {
4132 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4133
4134 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004135 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4136 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004137 {
4138 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004139 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4140 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4141 // 3.1 is still a bit ambiguous about the error, but future specs are
4142 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004143 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004144 return false;
4145 }
4146 else if (bufs[colorAttachment] >= maxColorAttachment)
4147 {
Jamie Madill437fa652016-05-03 15:13:24 -04004148 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004149 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004150 return false;
4151 }
4152 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4153 frameBufferId != 0)
4154 {
4155 // INVALID_OPERATION-GL is bound to buffer and ith argument
4156 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004157 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004158 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4159 return false;
4160 }
4161 }
4162
4163 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4164 // and n is not 1 or bufs is bound to value other than BACK and NONE
4165 if (frameBufferId == 0)
4166 {
4167 if (n != 1)
4168 {
Jamie Madill437fa652016-05-03 15:13:24 -04004169 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004170 "n must be 1 when GL is bound to the default framebuffer"));
4171 return false;
4172 }
4173
4174 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4175 {
Jamie Madill437fa652016-05-03 15:13:24 -04004176 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004177 GL_INVALID_OPERATION,
4178 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4179 return false;
4180 }
4181 }
4182
4183 return true;
4184}
4185
4186bool ValidateCopyTexSubImage2D(Context *context,
4187 GLenum target,
4188 GLint level,
4189 GLint xoffset,
4190 GLint yoffset,
4191 GLint x,
4192 GLint y,
4193 GLsizei width,
4194 GLsizei height)
4195{
Martin Radev1be913c2016-07-11 17:59:16 +03004196 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004197 {
4198 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4199 yoffset, x, y, width, height, 0);
4200 }
4201
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004202 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4203 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004204}
4205
Geoff Lang496c02d2016-10-20 11:38:11 -07004206bool ValidateGetBufferPointervBase(Context *context,
4207 GLenum target,
4208 GLenum pname,
4209 GLsizei *length,
4210 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004211{
Geoff Lang496c02d2016-10-20 11:38:11 -07004212 if (length)
4213 {
4214 *length = 0;
4215 }
4216
4217 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4218 {
4219 context->handleError(
4220 Error(GL_INVALID_OPERATION,
4221 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
4222 return false;
4223 }
4224
Olli Etuaho4f667482016-03-30 15:56:35 +03004225 if (!ValidBufferTarget(context, target))
4226 {
Jamie Madill437fa652016-05-03 15:13:24 -04004227 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004228 return false;
4229 }
4230
Geoff Lang496c02d2016-10-20 11:38:11 -07004231 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004232 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004233 case GL_BUFFER_MAP_POINTER:
4234 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004235
Geoff Lang496c02d2016-10-20 11:38:11 -07004236 default:
4237 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4238 return false;
4239 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004240
4241 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4242 // target bound to zero generate an INVALID_OPERATION error."
4243 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004244 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004245 {
Jamie Madill437fa652016-05-03 15:13:24 -04004246 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004247 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4248 return false;
4249 }
4250
Geoff Lang496c02d2016-10-20 11:38:11 -07004251 if (length)
4252 {
4253 *length = 1;
4254 }
4255
Olli Etuaho4f667482016-03-30 15:56:35 +03004256 return true;
4257}
4258
4259bool ValidateUnmapBufferBase(Context *context, GLenum target)
4260{
4261 if (!ValidBufferTarget(context, target))
4262 {
Jamie Madill437fa652016-05-03 15:13:24 -04004263 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004264 return false;
4265 }
4266
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004267 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004268
4269 if (buffer == nullptr || !buffer->isMapped())
4270 {
Jamie Madill437fa652016-05-03 15:13:24 -04004271 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004272 return false;
4273 }
4274
4275 return true;
4276}
4277
4278bool ValidateMapBufferRangeBase(Context *context,
4279 GLenum target,
4280 GLintptr offset,
4281 GLsizeiptr length,
4282 GLbitfield access)
4283{
4284 if (!ValidBufferTarget(context, target))
4285 {
Jamie Madill437fa652016-05-03 15:13:24 -04004286 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004287 return false;
4288 }
4289
4290 if (offset < 0 || length < 0)
4291 {
Jamie Madill437fa652016-05-03 15:13:24 -04004292 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004293 return false;
4294 }
4295
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004296 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004297
4298 if (!buffer)
4299 {
Jamie Madill437fa652016-05-03 15:13:24 -04004300 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004301 return false;
4302 }
4303
4304 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004305 CheckedNumeric<size_t> checkedOffset(offset);
4306 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004307
Jamie Madille2e406c2016-06-02 13:04:10 -04004308 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004309 {
Jamie Madill437fa652016-05-03 15:13:24 -04004310 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004311 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4312 return false;
4313 }
4314
4315 // Check for invalid bits in the mask
4316 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4317 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4318 GL_MAP_UNSYNCHRONIZED_BIT;
4319
4320 if (access & ~(allAccessBits))
4321 {
Jamie Madill437fa652016-05-03 15:13:24 -04004322 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004323 return false;
4324 }
4325
4326 if (length == 0)
4327 {
Jamie Madill437fa652016-05-03 15:13:24 -04004328 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004329 return false;
4330 }
4331
4332 if (buffer->isMapped())
4333 {
Jamie Madill437fa652016-05-03 15:13:24 -04004334 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004335 return false;
4336 }
4337
4338 // Check for invalid bit combinations
4339 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4340 {
Jamie Madill437fa652016-05-03 15:13:24 -04004341 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004342 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4343 return false;
4344 }
4345
4346 GLbitfield writeOnlyBits =
4347 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4348
4349 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4350 {
Jamie Madill437fa652016-05-03 15:13:24 -04004351 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004352 "Invalid access bits when mapping buffer for reading: 0x%X.",
4353 access));
4354 return false;
4355 }
4356
4357 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4358 {
Jamie Madill437fa652016-05-03 15:13:24 -04004359 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004360 GL_INVALID_OPERATION,
4361 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4362 return false;
4363 }
4364 return true;
4365}
4366
4367bool ValidateFlushMappedBufferRangeBase(Context *context,
4368 GLenum target,
4369 GLintptr offset,
4370 GLsizeiptr length)
4371{
4372 if (offset < 0 || length < 0)
4373 {
Jamie Madill437fa652016-05-03 15:13:24 -04004374 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004375 return false;
4376 }
4377
4378 if (!ValidBufferTarget(context, target))
4379 {
Jamie Madill437fa652016-05-03 15:13:24 -04004380 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004381 return false;
4382 }
4383
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004384 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004385
4386 if (buffer == nullptr)
4387 {
Jamie Madill437fa652016-05-03 15:13:24 -04004388 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004389 return false;
4390 }
4391
4392 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4393 {
Jamie Madill437fa652016-05-03 15:13:24 -04004394 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004395 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4396 return false;
4397 }
4398
4399 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004400 CheckedNumeric<size_t> checkedOffset(offset);
4401 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004402
Jamie Madille2e406c2016-06-02 13:04:10 -04004403 if (!checkedSize.IsValid() ||
4404 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004405 {
Jamie Madill437fa652016-05-03 15:13:24 -04004406 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004407 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4408 return false;
4409 }
4410
4411 return true;
4412}
4413
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004414bool ValidateGenerateMipmap(Context *context, GLenum target)
4415{
4416 if (!ValidTextureTarget(context, target))
4417 {
4418 context->handleError(Error(GL_INVALID_ENUM));
4419 return false;
4420 }
4421
4422 Texture *texture = context->getTargetTexture(target);
4423
4424 if (texture == nullptr)
4425 {
4426 context->handleError(Error(GL_INVALID_OPERATION));
4427 return false;
4428 }
4429
4430 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4431
4432 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4433 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4434 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4435 {
4436 context->handleError(Error(GL_INVALID_OPERATION));
4437 return false;
4438 }
4439
Jamie Madilla3944d42016-07-22 22:13:26 -04004440 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4441 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4442 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004443
4444 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4445 // unsized formats or that are color renderable and filterable. Since we do not track if
4446 // the texture was created with sized or unsized format (only sized formats are stored),
4447 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4448 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4449 // textures since they're the only texture format that can be created with unsized formats
4450 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4451 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004452 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4453 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004454 {
4455 context->handleError(Error(GL_INVALID_OPERATION));
4456 return false;
4457 }
4458
4459 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004460 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004461 {
4462 context->handleError(Error(GL_INVALID_OPERATION));
4463 return false;
4464 }
4465
4466 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004467 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004468 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4469 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4470 {
Geoff Lang55482a12016-11-21 16:54:01 -05004471 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004472 context->handleError(Error(GL_INVALID_OPERATION));
4473 return false;
4474 }
4475
4476 // Cube completeness check
4477 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4478 {
4479 context->handleError(Error(GL_INVALID_OPERATION));
4480 return false;
4481 }
4482
4483 return true;
4484}
4485
Olli Etuaho41997e72016-03-10 13:38:39 +02004486bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4487{
4488 return ValidateGenOrDelete(context, n);
4489}
4490
4491bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4492{
4493 return ValidateGenOrDelete(context, n);
4494}
4495
4496bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4497{
4498 return ValidateGenOrDelete(context, n);
4499}
4500
4501bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4502{
4503 return ValidateGenOrDelete(context, n);
4504}
4505
4506bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4507{
4508 return ValidateGenOrDelete(context, n);
4509}
4510
4511bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4512{
4513 return ValidateGenOrDelete(context, n);
4514}
4515
4516bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4517{
4518 return ValidateGenOrDelete(context, n);
4519}
4520
4521bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4522{
4523 return ValidateGenOrDelete(context, n);
4524}
4525
4526bool ValidateGenOrDelete(Context *context, GLint n)
4527{
4528 if (n < 0)
4529 {
Jamie Madill437fa652016-05-03 15:13:24 -04004530 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004531 return false;
4532 }
4533 return true;
4534}
4535
Geoff Langf41a7152016-09-19 15:11:17 -04004536bool ValidateEnable(Context *context, GLenum cap)
4537{
4538 if (!ValidCap(context, cap, false))
4539 {
4540 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4541 return false;
4542 }
4543
4544 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4545 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4546 {
4547 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4548 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4549
4550 // We also output an error message to the debugger window if tracing is active, so that
4551 // developers can see the error message.
4552 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004553 return false;
4554 }
4555
4556 return true;
4557}
4558
4559bool ValidateDisable(Context *context, GLenum cap)
4560{
4561 if (!ValidCap(context, cap, false))
4562 {
4563 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4564 return false;
4565 }
4566
4567 return true;
4568}
4569
4570bool ValidateIsEnabled(Context *context, GLenum cap)
4571{
4572 if (!ValidCap(context, cap, true))
4573 {
4574 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4575 return false;
4576 }
4577
4578 return true;
4579}
4580
Geoff Langff5b2d52016-09-07 11:32:23 -04004581bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4582{
4583 if (!context->getExtensions().robustClientMemory)
4584 {
4585 context->handleError(
4586 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4587 return false;
4588 }
4589
4590 if (bufSize < 0)
4591 {
4592 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4593 return false;
4594 }
4595
4596 return true;
4597}
4598
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004599bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4600{
4601 if (bufSize < numParams)
4602 {
4603 context->handleError(Error(GL_INVALID_OPERATION,
4604 "%u parameters are required but %i were provided.", numParams,
4605 bufSize));
4606 return false;
4607 }
4608
4609 return true;
4610}
4611
Geoff Langff5b2d52016-09-07 11:32:23 -04004612bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4613 GLenum target,
4614 GLenum attachment,
4615 GLenum pname,
4616 GLsizei *numParams)
4617{
4618 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4619 *numParams = 1;
4620
4621 if (!ValidFramebufferTarget(target))
4622 {
4623 context->handleError(Error(GL_INVALID_ENUM));
4624 return false;
4625 }
4626
4627 int clientVersion = context->getClientMajorVersion();
4628
4629 switch (pname)
4630 {
4631 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4632 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4633 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4634 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4635 break;
4636
4637 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4638 if (clientVersion < 3 && !context->getExtensions().sRGB)
4639 {
4640 context->handleError(Error(GL_INVALID_ENUM));
4641 return false;
4642 }
4643 break;
4644
4645 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4646 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4647 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4648 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4649 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4650 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4651 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4652 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4653 if (clientVersion < 3)
4654 {
4655 context->handleError(Error(GL_INVALID_ENUM));
4656 return false;
4657 }
4658 break;
4659
4660 default:
4661 context->handleError(Error(GL_INVALID_ENUM));
4662 return false;
4663 }
4664
4665 // Determine if the attachment is a valid enum
4666 switch (attachment)
4667 {
4668 case GL_BACK:
4669 case GL_FRONT:
4670 case GL_DEPTH:
4671 case GL_STENCIL:
4672 case GL_DEPTH_STENCIL_ATTACHMENT:
4673 if (clientVersion < 3)
4674 {
4675 context->handleError(Error(GL_INVALID_ENUM));
4676 return false;
4677 }
4678 break;
4679
4680 case GL_DEPTH_ATTACHMENT:
4681 case GL_STENCIL_ATTACHMENT:
4682 break;
4683
4684 default:
4685 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4686 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4687 {
4688 context->handleError(Error(GL_INVALID_ENUM));
4689 return false;
4690 }
4691 break;
4692 }
4693
4694 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4695 ASSERT(framebuffer);
4696
4697 if (framebuffer->id() == 0)
4698 {
4699 if (clientVersion < 3)
4700 {
4701 context->handleError(Error(GL_INVALID_OPERATION));
4702 return false;
4703 }
4704
4705 switch (attachment)
4706 {
4707 case GL_BACK:
4708 case GL_DEPTH:
4709 case GL_STENCIL:
4710 break;
4711
4712 default:
4713 context->handleError(Error(GL_INVALID_OPERATION));
4714 return false;
4715 }
4716 }
4717 else
4718 {
4719 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4720 {
4721 // Valid attachment query
4722 }
4723 else
4724 {
4725 switch (attachment)
4726 {
4727 case GL_DEPTH_ATTACHMENT:
4728 case GL_STENCIL_ATTACHMENT:
4729 break;
4730
4731 case GL_DEPTH_STENCIL_ATTACHMENT:
4732 if (!framebuffer->hasValidDepthStencil())
4733 {
4734 context->handleError(Error(GL_INVALID_OPERATION));
4735 return false;
4736 }
4737 break;
4738
4739 default:
4740 context->handleError(Error(GL_INVALID_OPERATION));
4741 return false;
4742 }
4743 }
4744 }
4745
4746 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4747 if (attachmentObject)
4748 {
4749 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4750 attachmentObject->type() == GL_TEXTURE ||
4751 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4752
4753 switch (pname)
4754 {
4755 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4756 if (attachmentObject->type() != GL_RENDERBUFFER &&
4757 attachmentObject->type() != GL_TEXTURE)
4758 {
4759 context->handleError(Error(GL_INVALID_ENUM));
4760 return false;
4761 }
4762 break;
4763
4764 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4765 if (attachmentObject->type() != GL_TEXTURE)
4766 {
4767 context->handleError(Error(GL_INVALID_ENUM));
4768 return false;
4769 }
4770 break;
4771
4772 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4773 if (attachmentObject->type() != GL_TEXTURE)
4774 {
4775 context->handleError(Error(GL_INVALID_ENUM));
4776 return false;
4777 }
4778 break;
4779
4780 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4781 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4782 {
4783 context->handleError(Error(GL_INVALID_OPERATION));
4784 return false;
4785 }
4786 break;
4787
4788 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4789 if (attachmentObject->type() != GL_TEXTURE)
4790 {
4791 context->handleError(Error(GL_INVALID_ENUM));
4792 return false;
4793 }
4794 break;
4795
4796 default:
4797 break;
4798 }
4799 }
4800 else
4801 {
4802 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4803 // is NONE, then querying any other pname will generate INVALID_ENUM.
4804
4805 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4806 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4807 // INVALID_OPERATION for all other pnames
4808
4809 switch (pname)
4810 {
4811 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4812 break;
4813
4814 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4815 if (clientVersion < 3)
4816 {
4817 context->handleError(Error(GL_INVALID_ENUM));
4818 return false;
4819 }
4820 break;
4821
4822 default:
4823 if (clientVersion < 3)
4824 {
4825 context->handleError(Error(GL_INVALID_ENUM));
4826 return false;
4827 }
4828 else
4829 {
4830 context->handleError(Error(GL_INVALID_OPERATION));
4831 return false;
4832 }
4833 }
4834 }
4835
4836 return true;
4837}
4838
4839bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4840 GLenum target,
4841 GLenum attachment,
4842 GLenum pname,
4843 GLsizei bufSize,
4844 GLsizei *numParams)
4845{
4846 if (!ValidateRobustEntryPoint(context, bufSize))
4847 {
4848 return false;
4849 }
4850
4851 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4852 {
4853 return false;
4854 }
4855
4856 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4857 {
4858 return false;
4859 }
4860
4861 return true;
4862}
4863
4864bool ValidateGetBufferParameteriv(ValidationContext *context,
4865 GLenum target,
4866 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004867 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004868{
Geoff Langebebe1c2016-10-14 12:01:31 -04004869 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004870}
4871
4872bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4873 GLenum target,
4874 GLenum pname,
4875 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004876 GLsizei *length,
4877 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004878{
4879 if (!ValidateRobustEntryPoint(context, bufSize))
4880 {
4881 return false;
4882 }
4883
Geoff Langebebe1c2016-10-14 12:01:31 -04004884 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004885 {
4886 return false;
4887 }
4888
Geoff Langebebe1c2016-10-14 12:01:31 -04004889 if (!ValidateRobustBufferSize(context, bufSize, *length))
4890 {
4891 return false;
4892 }
4893
4894 return true;
4895}
4896
4897bool ValidateGetBufferParameteri64v(ValidationContext *context,
4898 GLenum target,
4899 GLenum pname,
4900 GLint64 *params)
4901{
4902 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4903}
4904
4905bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4906 GLenum target,
4907 GLenum pname,
4908 GLsizei bufSize,
4909 GLsizei *length,
4910 GLint64 *params)
4911{
4912 if (!ValidateRobustEntryPoint(context, bufSize))
4913 {
4914 return false;
4915 }
4916
4917 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4918 {
4919 return false;
4920 }
4921
4922 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004923 {
4924 return false;
4925 }
4926
4927 return true;
4928}
4929
4930bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4931{
4932 // Currently, all GetProgramiv queries return 1 parameter
4933 *numParams = 1;
4934
4935 Program *programObject = GetValidProgram(context, program);
4936 if (!programObject)
4937 {
4938 return false;
4939 }
4940
4941 switch (pname)
4942 {
4943 case GL_DELETE_STATUS:
4944 case GL_LINK_STATUS:
4945 case GL_VALIDATE_STATUS:
4946 case GL_INFO_LOG_LENGTH:
4947 case GL_ATTACHED_SHADERS:
4948 case GL_ACTIVE_ATTRIBUTES:
4949 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4950 case GL_ACTIVE_UNIFORMS:
4951 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4952 break;
4953
4954 case GL_PROGRAM_BINARY_LENGTH:
4955 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4956 {
4957 context->handleError(Error(GL_INVALID_ENUM,
4958 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4959 "GL_OES_get_program_binary or ES 3.0."));
4960 return false;
4961 }
4962 break;
4963
4964 case GL_ACTIVE_UNIFORM_BLOCKS:
4965 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4966 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4967 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4968 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4969 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4970 if (context->getClientMajorVersion() < 3)
4971 {
4972 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4973 return false;
4974 }
4975 break;
4976
4977 default:
4978 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4979 return false;
4980 }
4981
4982 return true;
4983}
4984
4985bool ValidateGetProgramivRobustANGLE(Context *context,
4986 GLuint program,
4987 GLenum pname,
4988 GLsizei bufSize,
4989 GLsizei *numParams)
4990{
4991 if (!ValidateRobustEntryPoint(context, bufSize))
4992 {
4993 return false;
4994 }
4995
4996 if (!ValidateGetProgramiv(context, program, pname, numParams))
4997 {
4998 return false;
4999 }
5000
5001 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
5002 {
5003 return false;
5004 }
5005
5006 return true;
5007}
5008
Geoff Lang740d9022016-10-07 11:20:52 -04005009bool ValidateGetRenderbufferParameteriv(Context *context,
5010 GLenum target,
5011 GLenum pname,
5012 GLint *params)
5013{
5014 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
5015}
5016
5017bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
5018 GLenum target,
5019 GLenum pname,
5020 GLsizei bufSize,
5021 GLsizei *length,
5022 GLint *params)
5023{
5024 if (!ValidateRobustEntryPoint(context, bufSize))
5025 {
5026 return false;
5027 }
5028
5029 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5030 {
5031 return false;
5032 }
5033
5034 if (!ValidateRobustBufferSize(context, bufSize, *length))
5035 {
5036 return false;
5037 }
5038
5039 return true;
5040}
5041
Geoff Langd7d0ed32016-10-07 11:33:51 -04005042bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5043{
5044 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5045}
5046
5047bool ValidateGetShaderivRobustANGLE(Context *context,
5048 GLuint shader,
5049 GLenum pname,
5050 GLsizei bufSize,
5051 GLsizei *length,
5052 GLint *params)
5053{
5054 if (!ValidateRobustEntryPoint(context, bufSize))
5055 {
5056 return false;
5057 }
5058
5059 if (!ValidateGetShaderivBase(context, shader, pname, length))
5060 {
5061 return false;
5062 }
5063
5064 if (!ValidateRobustBufferSize(context, bufSize, *length))
5065 {
5066 return false;
5067 }
5068
5069 return true;
5070}
5071
Geoff Langc1984ed2016-10-07 12:41:00 -04005072bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5073{
5074 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5075}
5076
5077bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5078 GLenum target,
5079 GLenum pname,
5080 GLsizei bufSize,
5081 GLsizei *length,
5082 GLfloat *params)
5083{
5084 if (!ValidateRobustEntryPoint(context, bufSize))
5085 {
5086 return false;
5087 }
5088
5089 if (!ValidateGetTexParameterBase(context, target, pname, length))
5090 {
5091 return false;
5092 }
5093
5094 if (!ValidateRobustBufferSize(context, bufSize, *length))
5095 {
5096 return false;
5097 }
5098
5099 return true;
5100}
5101
5102bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5103{
5104 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5105}
5106
5107bool ValidateGetTexParameterivRobustANGLE(Context *context,
5108 GLenum target,
5109 GLenum pname,
5110 GLsizei bufSize,
5111 GLsizei *length,
5112 GLint *params)
5113{
5114 if (!ValidateRobustEntryPoint(context, bufSize))
5115 {
5116 return false;
5117 }
5118
5119 if (!ValidateGetTexParameterBase(context, target, pname, length))
5120 {
5121 return false;
5122 }
5123
5124 if (!ValidateRobustBufferSize(context, bufSize, *length))
5125 {
5126 return false;
5127 }
5128
5129 return true;
5130}
5131
5132bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5133{
5134 return ValidateTexParameterBase(context, target, pname, -1, &param);
5135}
5136
5137bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5138{
5139 return ValidateTexParameterBase(context, target, pname, -1, params);
5140}
5141
5142bool ValidateTexParameterfvRobustANGLE(Context *context,
5143 GLenum target,
5144 GLenum pname,
5145 GLsizei bufSize,
5146 const GLfloat *params)
5147{
5148 if (!ValidateRobustEntryPoint(context, bufSize))
5149 {
5150 return false;
5151 }
5152
5153 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5154}
5155
5156bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5157{
5158 return ValidateTexParameterBase(context, target, pname, -1, &param);
5159}
5160
5161bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5162{
5163 return ValidateTexParameterBase(context, target, pname, -1, params);
5164}
5165
5166bool ValidateTexParameterivRobustANGLE(Context *context,
5167 GLenum target,
5168 GLenum pname,
5169 GLsizei bufSize,
5170 const GLint *params)
5171{
5172 if (!ValidateRobustEntryPoint(context, bufSize))
5173 {
5174 return false;
5175 }
5176
5177 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5178}
5179
5180bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5181{
5182 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5183}
5184
5185bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5186 GLuint sampler,
5187 GLenum pname,
5188 GLuint bufSize,
5189 GLsizei *length,
5190 GLfloat *params)
5191{
5192 if (!ValidateRobustEntryPoint(context, bufSize))
5193 {
5194 return false;
5195 }
5196
5197 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5198 {
5199 return false;
5200 }
5201
5202 if (!ValidateRobustBufferSize(context, bufSize, *length))
5203 {
5204 return false;
5205 }
5206
5207 return true;
5208}
5209
5210bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5211{
5212 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5213}
5214
5215bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5216 GLuint sampler,
5217 GLenum pname,
5218 GLuint bufSize,
5219 GLsizei *length,
5220 GLint *params)
5221{
5222 if (!ValidateRobustEntryPoint(context, bufSize))
5223 {
5224 return false;
5225 }
5226
5227 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5228 {
5229 return false;
5230 }
5231
5232 if (!ValidateRobustBufferSize(context, bufSize, *length))
5233 {
5234 return false;
5235 }
5236
5237 return true;
5238}
5239
5240bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5241{
5242 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5243}
5244
5245bool ValidateSamplerParameterfv(Context *context,
5246 GLuint sampler,
5247 GLenum pname,
5248 const GLfloat *params)
5249{
5250 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5251}
5252
5253bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5254 GLuint sampler,
5255 GLenum pname,
5256 GLsizei bufSize,
5257 const GLfloat *params)
5258{
5259 if (!ValidateRobustEntryPoint(context, bufSize))
5260 {
5261 return false;
5262 }
5263
5264 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5265}
5266
5267bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5268{
5269 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5270}
5271
5272bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5273{
5274 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5275}
5276
5277bool ValidateSamplerParameterivRobustANGLE(Context *context,
5278 GLuint sampler,
5279 GLenum pname,
5280 GLsizei bufSize,
5281 const GLint *params)
5282{
5283 if (!ValidateRobustEntryPoint(context, bufSize))
5284 {
5285 return false;
5286 }
5287
5288 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5289}
5290
Geoff Lang0b031062016-10-13 14:30:04 -04005291bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5292{
5293 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5294}
5295
5296bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5297 GLuint index,
5298 GLenum pname,
5299 GLsizei bufSize,
5300 GLsizei *length,
5301 GLfloat *params)
5302{
5303 if (!ValidateRobustEntryPoint(context, bufSize))
5304 {
5305 return false;
5306 }
5307
5308 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5309 {
5310 return false;
5311 }
5312
5313 if (!ValidateRobustBufferSize(context, bufSize, *length))
5314 {
5315 return false;
5316 }
5317
5318 return true;
5319}
5320
5321bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5322{
5323 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5324}
5325
5326bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5327 GLuint index,
5328 GLenum pname,
5329 GLsizei bufSize,
5330 GLsizei *length,
5331 GLint *params)
5332{
5333 if (!ValidateRobustEntryPoint(context, bufSize))
5334 {
5335 return false;
5336 }
5337
5338 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5339 {
5340 return false;
5341 }
5342
5343 if (!ValidateRobustBufferSize(context, bufSize, *length))
5344 {
5345 return false;
5346 }
5347
5348 return true;
5349}
5350
5351bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5352{
5353 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5354}
5355
5356bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5357 GLuint index,
5358 GLenum pname,
5359 GLsizei bufSize,
5360 GLsizei *length,
5361 void **pointer)
5362{
5363 if (!ValidateRobustEntryPoint(context, bufSize))
5364 {
5365 return false;
5366 }
5367
5368 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5369 {
5370 return false;
5371 }
5372
5373 if (!ValidateRobustBufferSize(context, bufSize, *length))
5374 {
5375 return false;
5376 }
5377
5378 return true;
5379}
5380
5381bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5382{
5383 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5384}
5385
5386bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5387 GLuint index,
5388 GLenum pname,
5389 GLsizei bufSize,
5390 GLsizei *length,
5391 GLint *params)
5392{
5393 if (!ValidateRobustEntryPoint(context, bufSize))
5394 {
5395 return false;
5396 }
5397
5398 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5399 {
5400 return false;
5401 }
5402
5403 if (!ValidateRobustBufferSize(context, bufSize, *length))
5404 {
5405 return false;
5406 }
5407
5408 return true;
5409}
5410
5411bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5412{
5413 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5414}
5415
5416bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5417 GLuint index,
5418 GLenum pname,
5419 GLsizei bufSize,
5420 GLsizei *length,
5421 GLuint *params)
5422{
5423 if (!ValidateRobustEntryPoint(context, bufSize))
5424 {
5425 return false;
5426 }
5427
5428 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5429 {
5430 return false;
5431 }
5432
5433 if (!ValidateRobustBufferSize(context, bufSize, *length))
5434 {
5435 return false;
5436 }
5437
5438 return true;
5439}
5440
Geoff Lang6899b872016-10-14 11:30:13 -04005441bool ValidateGetActiveUniformBlockiv(Context *context,
5442 GLuint program,
5443 GLuint uniformBlockIndex,
5444 GLenum pname,
5445 GLint *params)
5446{
5447 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5448}
5449
5450bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5451 GLuint program,
5452 GLuint uniformBlockIndex,
5453 GLenum pname,
5454 GLsizei bufSize,
5455 GLsizei *length,
5456 GLint *params)
5457{
5458 if (!ValidateRobustEntryPoint(context, bufSize))
5459 {
5460 return false;
5461 }
5462
5463 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5464 {
5465 return false;
5466 }
5467
5468 if (!ValidateRobustBufferSize(context, bufSize, *length))
5469 {
5470 return false;
5471 }
5472
5473 return true;
5474}
5475
Geoff Lang0a9661f2016-10-20 10:59:20 -07005476bool ValidateGetInternalFormativ(Context *context,
5477 GLenum target,
5478 GLenum internalformat,
5479 GLenum pname,
5480 GLsizei bufSize,
5481 GLint *params)
5482{
5483 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5484 nullptr);
5485}
5486
5487bool ValidateGetInternalFormativRobustANGLE(Context *context,
5488 GLenum target,
5489 GLenum internalformat,
5490 GLenum pname,
5491 GLsizei bufSize,
5492 GLsizei *length,
5493 GLint *params)
5494{
5495 if (!ValidateRobustEntryPoint(context, bufSize))
5496 {
5497 return false;
5498 }
5499
5500 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5501 {
5502 return false;
5503 }
5504
5505 if (!ValidateRobustBufferSize(context, bufSize, *length))
5506 {
5507 return false;
5508 }
5509
5510 return true;
5511}
5512
Jamie Madillc29968b2016-01-20 11:17:23 -05005513} // namespace gl