blob: 1095017cdda3663535e174be13a744413c4858c7 [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();
244 if (!readBuffer)
245 {
246 context->handleError(Error(GL_INVALID_OPERATION));
247 return false;
248 }
249
250 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
251 GLenum currentType = framebuffer->getImplementationColorReadType();
252 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
253
254 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
255 bool validFormatTypeCombination =
256 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
257
258 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
259 {
260 context->handleError(Error(GL_INVALID_OPERATION));
261 return false;
262 }
263
264 // Check for pixel pack buffer related API errors
265 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
266 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
267 {
268 // ...the buffer object's data store is currently mapped.
269 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
270 return false;
271 }
272
273 // .. the data would be packed to the buffer object such that the memory writes required
274 // would exceed the data store size.
275 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
276 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
277 const gl::Extents size(width, height, 1);
278 const auto &pack = context->getGLState().getPackState();
279
280 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
281 if (endByteOrErr.isError())
282 {
283 context->handleError(endByteOrErr.getError());
284 return false;
285 }
286
287 size_t endByte = endByteOrErr.getResult();
288 if (bufSize >= 0)
289 {
290
291 if (static_cast<size_t>(bufSize) < endByte)
292 {
293 context->handleError(
294 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
295 return false;
296 }
297 }
298
299 if (pixelPackBuffer != nullptr)
300 {
301 CheckedNumeric<size_t> checkedEndByte(endByte);
302 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
303 checkedEndByte += checkedOffset;
304
305 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
306 {
307 // Overflow past the end of the buffer
308 context->handleError(
309 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
310 return false;
311 }
312 }
313
314 if (length != nullptr)
315 {
316 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
317 {
318 context->handleError(
319 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
320 return false;
321 }
322
323 *length = static_cast<GLsizei>(endByte);
324 }
325
326 return true;
327}
328
Geoff Lang740d9022016-10-07 11:20:52 -0400329bool ValidateGetRenderbufferParameterivBase(Context *context,
330 GLenum target,
331 GLenum pname,
332 GLsizei *length)
333{
334 if (length)
335 {
336 *length = 0;
337 }
338
339 if (target != GL_RENDERBUFFER)
340 {
341 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
342 return false;
343 }
344
345 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
346 if (renderbuffer == nullptr)
347 {
348 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
349 return false;
350 }
351
352 switch (pname)
353 {
354 case GL_RENDERBUFFER_WIDTH:
355 case GL_RENDERBUFFER_HEIGHT:
356 case GL_RENDERBUFFER_INTERNAL_FORMAT:
357 case GL_RENDERBUFFER_RED_SIZE:
358 case GL_RENDERBUFFER_GREEN_SIZE:
359 case GL_RENDERBUFFER_BLUE_SIZE:
360 case GL_RENDERBUFFER_ALPHA_SIZE:
361 case GL_RENDERBUFFER_DEPTH_SIZE:
362 case GL_RENDERBUFFER_STENCIL_SIZE:
363 break;
364
365 case GL_RENDERBUFFER_SAMPLES_ANGLE:
366 if (!context->getExtensions().framebufferMultisample)
367 {
368 context->handleError(
369 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
370 return false;
371 }
372 break;
373
374 default:
375 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
376 return false;
377 }
378
379 if (length)
380 {
381 *length = 1;
382 }
383 return true;
384}
385
Geoff Langd7d0ed32016-10-07 11:33:51 -0400386bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
387{
388 if (length)
389 {
390 *length = 0;
391 }
392
393 if (GetValidShader(context, shader) == nullptr)
394 {
395 return false;
396 }
397
398 switch (pname)
399 {
400 case GL_SHADER_TYPE:
401 case GL_DELETE_STATUS:
402 case GL_COMPILE_STATUS:
403 case GL_INFO_LOG_LENGTH:
404 case GL_SHADER_SOURCE_LENGTH:
405 break;
406
407 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
408 if (!context->getExtensions().translatedShaderSource)
409 {
410 context->handleError(
411 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
412 return false;
413 }
414 break;
415
416 default:
417 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
418 return false;
419 }
420
421 if (length)
422 {
423 *length = 1;
424 }
425 return true;
426}
427
Geoff Langc1984ed2016-10-07 12:41:00 -0400428bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
429{
430 if (length)
431 {
432 *length = 0;
433 }
434
435 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
436 {
437 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
438 return false;
439 }
440
441 if (context->getTargetTexture(target) == nullptr)
442 {
443 // Should only be possible for external textures
444 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
445 return false;
446 }
447
448 switch (pname)
449 {
450 case GL_TEXTURE_MAG_FILTER:
451 case GL_TEXTURE_MIN_FILTER:
452 case GL_TEXTURE_WRAP_S:
453 case GL_TEXTURE_WRAP_T:
454 break;
455
456 case GL_TEXTURE_USAGE_ANGLE:
457 if (!context->getExtensions().textureUsage)
458 {
459 context->handleError(
460 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
461 return false;
462 }
463 break;
464
465 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
466 if (!context->getExtensions().textureFilterAnisotropic)
467 {
468 context->handleError(
469 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
470 return false;
471 }
472 break;
473
474 case GL_TEXTURE_IMMUTABLE_FORMAT:
475 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
476 {
477 context->handleError(
478 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
479 return false;
480 }
481 break;
482
483 case GL_TEXTURE_WRAP_R:
484 case GL_TEXTURE_IMMUTABLE_LEVELS:
485 case GL_TEXTURE_SWIZZLE_R:
486 case GL_TEXTURE_SWIZZLE_G:
487 case GL_TEXTURE_SWIZZLE_B:
488 case GL_TEXTURE_SWIZZLE_A:
489 case GL_TEXTURE_BASE_LEVEL:
490 case GL_TEXTURE_MAX_LEVEL:
491 case GL_TEXTURE_MIN_LOD:
492 case GL_TEXTURE_MAX_LOD:
493 case GL_TEXTURE_COMPARE_MODE:
494 case GL_TEXTURE_COMPARE_FUNC:
495 if (context->getClientMajorVersion() < 3)
496 {
497 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
498 return false;
499 }
500 break;
501
Geoff Lang81c6b572016-10-19 14:07:52 -0700502 case GL_TEXTURE_SRGB_DECODE_EXT:
503 if (!context->getExtensions().textureSRGBDecode)
504 {
505 context->handleError(
506 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
507 return false;
508 }
509 break;
510
Geoff Langc1984ed2016-10-07 12:41:00 -0400511 default:
512 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
513 return false;
514 }
515
516 if (length)
517 {
518 *length = 1;
519 }
520 return true;
521}
522
523template <typename ParamType>
524bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
525{
526 switch (ConvertToGLenum(params[0]))
527 {
528 case GL_CLAMP_TO_EDGE:
529 break;
530
531 case GL_REPEAT:
532 case GL_MIRRORED_REPEAT:
533 if (isExternalTextureTarget)
534 {
535 // OES_EGL_image_external specifies this error.
536 context->handleError(Error(
537 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
538 return false;
539 }
540 break;
541
542 default:
543 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
544 return false;
545 }
546
547 return true;
548}
549
550template <typename ParamType>
551bool ValidateTextureMinFilterValue(Context *context,
552 ParamType *params,
553 bool isExternalTextureTarget)
554{
555 switch (ConvertToGLenum(params[0]))
556 {
557 case GL_NEAREST:
558 case GL_LINEAR:
559 break;
560
561 case GL_NEAREST_MIPMAP_NEAREST:
562 case GL_LINEAR_MIPMAP_NEAREST:
563 case GL_NEAREST_MIPMAP_LINEAR:
564 case GL_LINEAR_MIPMAP_LINEAR:
565 if (isExternalTextureTarget)
566 {
567 // OES_EGL_image_external specifies this error.
568 context->handleError(
569 Error(GL_INVALID_ENUM,
570 "external textures only support NEAREST and LINEAR filtering"));
571 return false;
572 }
573 break;
574
575 default:
576 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
577 return false;
578 }
579
580 return true;
581}
582
583template <typename ParamType>
584bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
585{
586 switch (ConvertToGLenum(params[0]))
587 {
588 case GL_NEAREST:
589 case GL_LINEAR:
590 break;
591
592 default:
593 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
594 return false;
595 }
596
597 return true;
598}
599
600template <typename ParamType>
601bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
602{
603 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
604 switch (ConvertToGLenum(params[0]))
605 {
606 case GL_NONE:
607 case GL_COMPARE_REF_TO_TEXTURE:
608 break;
609
610 default:
611 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
612 return false;
613 }
614
615 return true;
616}
617
618template <typename ParamType>
619bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
620{
621 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
622 switch (ConvertToGLenum(params[0]))
623 {
624 case GL_LEQUAL:
625 case GL_GEQUAL:
626 case GL_LESS:
627 case GL_GREATER:
628 case GL_EQUAL:
629 case GL_NOTEQUAL:
630 case GL_ALWAYS:
631 case GL_NEVER:
632 break;
633
634 default:
635 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
636 return false;
637 }
638
639 return true;
640}
641
642template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700643bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
644{
645 if (!context->getExtensions().textureSRGBDecode)
646 {
647 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
648 return false;
649 }
650
651 switch (ConvertToGLenum(params[0]))
652 {
653 case GL_DECODE_EXT:
654 case GL_SKIP_DECODE_EXT:
655 break;
656
657 default:
658 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
659 return false;
660 }
661
662 return true;
663}
664
665template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400666bool ValidateTexParameterBase(Context *context,
667 GLenum target,
668 GLenum pname,
669 GLsizei bufSize,
670 ParamType *params)
671{
672 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
673 {
674 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
675 return false;
676 }
677
678 if (context->getTargetTexture(target) == nullptr)
679 {
680 // Should only be possible for external textures
681 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
682 return false;
683 }
684
685 const GLsizei minBufSize = 1;
686 if (bufSize >= 0 && bufSize < minBufSize)
687 {
688 context->handleError(
689 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
690 return false;
691 }
692
693 switch (pname)
694 {
695 case GL_TEXTURE_WRAP_R:
696 case GL_TEXTURE_SWIZZLE_R:
697 case GL_TEXTURE_SWIZZLE_G:
698 case GL_TEXTURE_SWIZZLE_B:
699 case GL_TEXTURE_SWIZZLE_A:
700 case GL_TEXTURE_BASE_LEVEL:
701 case GL_TEXTURE_MAX_LEVEL:
702 case GL_TEXTURE_COMPARE_MODE:
703 case GL_TEXTURE_COMPARE_FUNC:
704 case GL_TEXTURE_MIN_LOD:
705 case GL_TEXTURE_MAX_LOD:
706 if (context->getClientMajorVersion() < 3)
707 {
708 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
709 return false;
710 }
711 if (target == GL_TEXTURE_EXTERNAL_OES &&
712 !context->getExtensions().eglImageExternalEssl3)
713 {
714 context->handleError(Error(GL_INVALID_ENUM,
715 "ES3 texture parameters are not available without "
716 "GL_OES_EGL_image_external_essl3."));
717 return false;
718 }
719 break;
720
721 default:
722 break;
723 }
724
725 switch (pname)
726 {
727 case GL_TEXTURE_WRAP_S:
728 case GL_TEXTURE_WRAP_T:
729 case GL_TEXTURE_WRAP_R:
730 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
731 {
732 return false;
733 }
734 break;
735
736 case GL_TEXTURE_MIN_FILTER:
737 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
738 {
739 return false;
740 }
741 break;
742
743 case GL_TEXTURE_MAG_FILTER:
744 if (!ValidateTextureMagFilterValue(context, params))
745 {
746 return false;
747 }
748 break;
749
750 case GL_TEXTURE_USAGE_ANGLE:
751 switch (ConvertToGLenum(params[0]))
752 {
753 case GL_NONE:
754 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
755 break;
756
757 default:
758 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
759 return false;
760 }
761 break;
762
763 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
764 if (!context->getExtensions().textureFilterAnisotropic)
765 {
766 context->handleError(
767 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
768 return false;
769 }
770
771 // we assume the parameter passed to this validation method is truncated, not rounded
772 if (params[0] < 1)
773 {
774 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
775 return false;
776 }
777 break;
778
779 case GL_TEXTURE_MIN_LOD:
780 case GL_TEXTURE_MAX_LOD:
781 // any value is permissible
782 break;
783
784 case GL_TEXTURE_COMPARE_MODE:
785 if (!ValidateTextureCompareModeValue(context, params))
786 {
787 return false;
788 }
789 break;
790
791 case GL_TEXTURE_COMPARE_FUNC:
792 if (!ValidateTextureCompareFuncValue(context, params))
793 {
794 return false;
795 }
796 break;
797
798 case GL_TEXTURE_SWIZZLE_R:
799 case GL_TEXTURE_SWIZZLE_G:
800 case GL_TEXTURE_SWIZZLE_B:
801 case GL_TEXTURE_SWIZZLE_A:
802 switch (ConvertToGLenum(params[0]))
803 {
804 case GL_RED:
805 case GL_GREEN:
806 case GL_BLUE:
807 case GL_ALPHA:
808 case GL_ZERO:
809 case GL_ONE:
810 break;
811
812 default:
813 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
814 return false;
815 }
816 break;
817
818 case GL_TEXTURE_BASE_LEVEL:
819 if (params[0] < 0)
820 {
821 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
822 return false;
823 }
824 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
825 {
826 context->handleError(
827 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
828 return false;
829 }
830 break;
831
832 case GL_TEXTURE_MAX_LEVEL:
833 if (params[0] < 0)
834 {
835 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
836 return false;
837 }
838 break;
839
Geoff Lang3b573612016-10-31 14:08:10 -0400840 case GL_DEPTH_STENCIL_TEXTURE_MODE:
841 if (context->getClientVersion() < Version(3, 1))
842 {
843 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
844 return false;
845 }
Geoff Lang9f090372016-12-02 10:20:43 -0500846 switch (ConvertToGLenum(params[0]))
847 {
848 case GL_DEPTH_COMPONENT:
849 case GL_STENCIL_INDEX:
850 break;
851
852 default:
853 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
854 return false;
855 }
Geoff Lang3b573612016-10-31 14:08:10 -0400856 break;
857
Geoff Lang81c6b572016-10-19 14:07:52 -0700858 case GL_TEXTURE_SRGB_DECODE_EXT:
859 if (!ValidateTextureSRGBDecodeValue(context, params))
860 {
861 return false;
862 }
863 break;
864
Geoff Langc1984ed2016-10-07 12:41:00 -0400865 default:
866 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
867 return false;
868 }
869
870 return true;
871}
872
873template <typename ParamType>
874bool ValidateSamplerParameterBase(Context *context,
875 GLuint sampler,
876 GLenum pname,
877 GLsizei bufSize,
878 ParamType *params)
879{
880 if (context->getClientMajorVersion() < 3)
881 {
882 context->handleError(
883 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
884 return false;
885 }
886
887 if (!context->isSampler(sampler))
888 {
889 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
890 return false;
891 }
892
893 const GLsizei minBufSize = 1;
894 if (bufSize >= 0 && bufSize < minBufSize)
895 {
896 context->handleError(
897 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
898 return false;
899 }
900
901 switch (pname)
902 {
903 case GL_TEXTURE_WRAP_S:
904 case GL_TEXTURE_WRAP_T:
905 case GL_TEXTURE_WRAP_R:
906 if (!ValidateTextureWrapModeValue(context, params, false))
907 {
908 return false;
909 }
910 break;
911
912 case GL_TEXTURE_MIN_FILTER:
913 if (!ValidateTextureMinFilterValue(context, params, false))
914 {
915 return false;
916 }
917 break;
918
919 case GL_TEXTURE_MAG_FILTER:
920 if (!ValidateTextureMagFilterValue(context, params))
921 {
922 return false;
923 }
924 break;
925
926 case GL_TEXTURE_MIN_LOD:
927 case GL_TEXTURE_MAX_LOD:
928 // any value is permissible
929 break;
930
931 case GL_TEXTURE_COMPARE_MODE:
932 if (!ValidateTextureCompareModeValue(context, params))
933 {
934 return false;
935 }
936 break;
937
938 case GL_TEXTURE_COMPARE_FUNC:
939 if (!ValidateTextureCompareFuncValue(context, params))
940 {
941 return false;
942 }
943 break;
944
Geoff Lang81c6b572016-10-19 14:07:52 -0700945 case GL_TEXTURE_SRGB_DECODE_EXT:
946 if (!ValidateTextureSRGBDecodeValue(context, params))
947 {
948 return false;
949 }
950 break;
951
Geoff Langc1984ed2016-10-07 12:41:00 -0400952 default:
953 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
954 return false;
955 }
956
957 return true;
958}
959
960bool ValidateGetSamplerParameterBase(Context *context,
961 GLuint sampler,
962 GLenum pname,
963 GLsizei *length)
964{
965 if (length)
966 {
967 *length = 0;
968 }
969
970 if (context->getClientMajorVersion() < 3)
971 {
972 context->handleError(
973 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
974 return false;
975 }
976
977 if (!context->isSampler(sampler))
978 {
979 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
980 return false;
981 }
982
983 switch (pname)
984 {
985 case GL_TEXTURE_WRAP_S:
986 case GL_TEXTURE_WRAP_T:
987 case GL_TEXTURE_WRAP_R:
988 case GL_TEXTURE_MIN_FILTER:
989 case GL_TEXTURE_MAG_FILTER:
990 case GL_TEXTURE_MIN_LOD:
991 case GL_TEXTURE_MAX_LOD:
992 case GL_TEXTURE_COMPARE_MODE:
993 case GL_TEXTURE_COMPARE_FUNC:
994 break;
995
Geoff Lang81c6b572016-10-19 14:07:52 -0700996 case GL_TEXTURE_SRGB_DECODE_EXT:
997 if (!context->getExtensions().textureSRGBDecode)
998 {
999 context->handleError(
1000 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
1001 return false;
1002 }
1003 break;
1004
Geoff Langc1984ed2016-10-07 12:41:00 -04001005 default:
1006 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1007 return false;
1008 }
1009
1010 if (length)
1011 {
1012 *length = 1;
1013 }
1014 return true;
1015}
1016
Geoff Lang0b031062016-10-13 14:30:04 -04001017bool ValidateGetVertexAttribBase(Context *context,
1018 GLuint index,
1019 GLenum pname,
1020 GLsizei *length,
1021 bool pointer,
1022 bool pureIntegerEntryPoint)
1023{
1024 if (length)
1025 {
1026 *length = 0;
1027 }
1028
1029 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1030 {
1031 context->handleError(
1032 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1033 return false;
1034 }
1035
1036 if (index >= context->getCaps().maxVertexAttributes)
1037 {
1038 context->handleError(Error(
1039 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1040 return false;
1041 }
1042
1043 if (pointer)
1044 {
1045 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1046 {
1047 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1048 return false;
1049 }
1050 }
1051 else
1052 {
1053 switch (pname)
1054 {
1055 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1056 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1057 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1058 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1059 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1060 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1061 case GL_CURRENT_VERTEX_ATTRIB:
1062 break;
1063
1064 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1065 static_assert(
1066 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1067 "ANGLE extension enums not equal to GL enums.");
1068 if (context->getClientMajorVersion() < 3 &&
1069 !context->getExtensions().instancedArrays)
1070 {
1071 context->handleError(Error(GL_INVALID_ENUM,
1072 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1073 "3.0 or GL_ANGLE_instanced_arrays."));
1074 return false;
1075 }
1076 break;
1077
1078 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1079 if (context->getClientMajorVersion() < 3)
1080 {
1081 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1082 return false;
1083 }
1084 break;
1085
1086 default:
1087 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1088 return false;
1089 }
1090 }
1091
1092 if (length)
1093 {
1094 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1095 {
1096 *length = 4;
1097 }
1098 else
1099 {
1100 *length = 1;
1101 }
1102 }
1103
1104 return true;
1105}
1106
Geoff Lang6899b872016-10-14 11:30:13 -04001107bool ValidateGetActiveUniformBlockivBase(Context *context,
1108 GLuint program,
1109 GLuint uniformBlockIndex,
1110 GLenum pname,
1111 GLsizei *length)
1112{
1113 if (length)
1114 {
1115 *length = 0;
1116 }
1117
1118 if (context->getClientMajorVersion() < 3)
1119 {
1120 context->handleError(
1121 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1122 return false;
1123 }
1124
1125 Program *programObject = GetValidProgram(context, program);
1126 if (!programObject)
1127 {
1128 return false;
1129 }
1130
1131 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1132 {
1133 context->handleError(
1134 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1135 return false;
1136 }
1137
1138 switch (pname)
1139 {
1140 case GL_UNIFORM_BLOCK_BINDING:
1141 case GL_UNIFORM_BLOCK_DATA_SIZE:
1142 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1143 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1144 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1145 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1146 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1147 break;
1148
1149 default:
1150 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1151 return false;
1152 }
1153
1154 if (length)
1155 {
1156 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1157 {
1158 const UniformBlock &uniformBlock =
1159 programObject->getUniformBlockByIndex(uniformBlockIndex);
1160 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1161 }
1162 else
1163 {
1164 *length = 1;
1165 }
1166 }
1167
1168 return true;
1169}
1170
Geoff Langebebe1c2016-10-14 12:01:31 -04001171bool ValidateGetBufferParameterBase(ValidationContext *context,
1172 GLenum target,
1173 GLenum pname,
1174 bool pointerVersion,
1175 GLsizei *numParams)
1176{
1177 if (numParams)
1178 {
1179 *numParams = 0;
1180 }
1181
1182 if (!ValidBufferTarget(context, target))
1183 {
1184 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1185 return false;
1186 }
1187
1188 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1189 if (!buffer)
1190 {
1191 // A null buffer means that "0" is bound to the requested buffer target
1192 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1193 return false;
1194 }
1195
1196 const Extensions &extensions = context->getExtensions();
1197
1198 switch (pname)
1199 {
1200 case GL_BUFFER_USAGE:
1201 case GL_BUFFER_SIZE:
1202 break;
1203
1204 case GL_BUFFER_ACCESS_OES:
1205 if (!extensions.mapBuffer)
1206 {
1207 context->handleError(
1208 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
1209 return false;
1210 }
1211 break;
1212
1213 case GL_BUFFER_MAPPED:
1214 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1215 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1216 !extensions.mapBufferRange)
1217 {
1218 context->handleError(Error(
1219 GL_INVALID_ENUM,
1220 "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
1221 return false;
1222 }
1223 break;
1224
1225 case GL_BUFFER_MAP_POINTER:
1226 if (!pointerVersion)
1227 {
1228 context->handleError(
1229 Error(GL_INVALID_ENUM,
1230 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1231 return false;
1232 }
1233 break;
1234
1235 case GL_BUFFER_ACCESS_FLAGS:
1236 case GL_BUFFER_MAP_OFFSET:
1237 case GL_BUFFER_MAP_LENGTH:
1238 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1239 {
1240 context->handleError(Error(
1241 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1242 return false;
1243 }
1244 break;
1245
1246 default:
1247 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1248 return false;
1249 }
1250
1251 // All buffer parameter queries return one value.
1252 if (numParams)
1253 {
1254 *numParams = 1;
1255 }
1256
1257 return true;
1258}
1259
Geoff Lang0a9661f2016-10-20 10:59:20 -07001260bool ValidateGetInternalFormativBase(Context *context,
1261 GLenum target,
1262 GLenum internalformat,
1263 GLenum pname,
1264 GLsizei bufSize,
1265 GLsizei *numParams)
1266{
1267 if (numParams)
1268 {
1269 *numParams = 0;
1270 }
1271
1272 if (context->getClientMajorVersion() < 3)
1273 {
1274 context->handleError(
1275 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1276 return false;
1277 }
1278
1279 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1280 if (!formatCaps.renderable)
1281 {
1282 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1283 return false;
1284 }
1285
1286 switch (target)
1287 {
1288 case GL_RENDERBUFFER:
1289 break;
1290
1291 default:
1292 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1293 return false;
1294 }
1295
1296 if (bufSize < 0)
1297 {
1298 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1299 return false;
1300 }
1301
1302 GLsizei maxWriteParams = 0;
1303 switch (pname)
1304 {
1305 case GL_NUM_SAMPLE_COUNTS:
1306 maxWriteParams = 1;
1307 break;
1308
1309 case GL_SAMPLES:
1310 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1311 break;
1312
1313 default:
1314 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1315 return false;
1316 }
1317
1318 if (numParams)
1319 {
1320 // glGetInternalFormativ will not overflow bufSize
1321 *numParams = std::min(bufSize, maxWriteParams);
1322 }
1323
1324 return true;
1325}
1326
Geoff Langf41a7152016-09-19 15:11:17 -04001327} // anonymous namespace
1328
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001329bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001330{
Jamie Madilld7460c72014-01-21 16:38:14 -05001331 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001332 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001333 case GL_TEXTURE_2D:
1334 case GL_TEXTURE_CUBE_MAP:
1335 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001336
He Yunchaoced53ae2016-11-29 15:00:51 +08001337 case GL_TEXTURE_3D:
1338 case GL_TEXTURE_2D_ARRAY:
1339 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001340
He Yunchaoced53ae2016-11-29 15:00:51 +08001341 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001342 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001343
He Yunchaoced53ae2016-11-29 15:00:51 +08001344 default:
1345 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001346 }
Jamie Madill35d15012013-10-07 10:46:37 -04001347}
1348
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001349bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1350{
1351 switch (target)
1352 {
1353 case GL_TEXTURE_2D:
1354 case GL_TEXTURE_CUBE_MAP:
1355 return true;
1356
1357 default:
1358 return false;
1359 }
1360}
1361
1362bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1363{
1364 switch (target)
1365 {
1366 case GL_TEXTURE_3D:
1367 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001368 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001369
1370 default:
1371 return false;
1372 }
1373}
1374
Ian Ewellbda75592016-04-18 17:25:54 -04001375// Most texture GL calls are not compatible with external textures, so we have a separate validation
1376// function for use in the GL calls that do
1377bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1378{
1379 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1380 (context->getExtensions().eglImageExternal ||
1381 context->getExtensions().eglStreamConsumerExternal);
1382}
1383
Shannon Woods4dfed832014-03-17 20:03:39 -04001384// This function differs from ValidTextureTarget in that the target must be
1385// usable as the destination of a 2D operation-- so a cube face is valid, but
1386// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001387// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001388bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001389{
1390 switch (target)
1391 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001392 case GL_TEXTURE_2D:
1393 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1394 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1395 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1396 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1397 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1398 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1399 return true;
1400 default:
1401 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001402 }
1403}
1404
1405bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1406{
1407 switch (target)
1408 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001409 case GL_TEXTURE_3D:
1410 case GL_TEXTURE_2D_ARRAY:
1411 return true;
1412 default:
1413 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001414 }
1415}
1416
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001417bool ValidFramebufferTarget(GLenum target)
1418{
He Yunchaoced53ae2016-11-29 15:00:51 +08001419 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1420 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001421 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001422
1423 switch (target)
1424 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001425 case GL_FRAMEBUFFER:
1426 return true;
1427 case GL_READ_FRAMEBUFFER:
1428 return true;
1429 case GL_DRAW_FRAMEBUFFER:
1430 return true;
1431 default:
1432 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001433 }
1434}
1435
Jamie Madill29639852016-09-02 15:00:09 -04001436bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001437{
1438 switch (target)
1439 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001440 case GL_ARRAY_BUFFER:
1441 case GL_ELEMENT_ARRAY_BUFFER:
1442 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001443
He Yunchaoced53ae2016-11-29 15:00:51 +08001444 case GL_PIXEL_PACK_BUFFER:
1445 case GL_PIXEL_UNPACK_BUFFER:
1446 return (context->getExtensions().pixelBufferObject ||
1447 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001448
He Yunchaoced53ae2016-11-29 15:00:51 +08001449 case GL_COPY_READ_BUFFER:
1450 case GL_COPY_WRITE_BUFFER:
1451 case GL_TRANSFORM_FEEDBACK_BUFFER:
1452 case GL_UNIFORM_BUFFER:
1453 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001454
He Yunchaoced53ae2016-11-29 15:00:51 +08001455 case GL_ATOMIC_COUNTER_BUFFER:
1456 case GL_SHADER_STORAGE_BUFFER:
1457 case GL_DRAW_INDIRECT_BUFFER:
1458 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001459 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001460
He Yunchaoced53ae2016-11-29 15:00:51 +08001461 default:
1462 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001463 }
1464}
1465
Jamie Madillc29968b2016-01-20 11:17:23 -05001466bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001467{
Jamie Madillc29968b2016-01-20 11:17:23 -05001468 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001469 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001470 switch (target)
1471 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001472 case GL_TEXTURE_2D:
1473 maxDimension = caps.max2DTextureSize;
1474 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001475 case GL_TEXTURE_CUBE_MAP:
1476 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1477 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1478 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1479 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1480 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1481 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1482 maxDimension = caps.maxCubeMapTextureSize;
1483 break;
1484 case GL_TEXTURE_3D:
1485 maxDimension = caps.max3DTextureSize;
1486 break;
1487 case GL_TEXTURE_2D_ARRAY:
1488 maxDimension = caps.max2DTextureSize;
1489 break;
1490 default:
1491 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001492 }
1493
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001494 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001495}
1496
Geoff Langcc507aa2016-12-12 10:09:52 -05001497bool ValidImageSizeParameters(const ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001498 GLenum target,
1499 GLint level,
1500 GLsizei width,
1501 GLsizei height,
1502 GLsizei depth,
1503 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001504{
1505 if (level < 0 || width < 0 || height < 0 || depth < 0)
1506 {
1507 return false;
1508 }
1509
Austin Kinross08528e12015-10-07 16:24:40 -07001510 // TexSubImage parameters can be NPOT without textureNPOT extension,
1511 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001512 bool hasNPOTSupport =
1513 context->getExtensions().textureNPOT && context->getClientVersion() >= Version(3, 0);
1514 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001515 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001516 {
1517 return false;
1518 }
1519
1520 if (!ValidMipLevel(context, target, level))
1521 {
1522 return false;
1523 }
1524
1525 return true;
1526}
1527
Geoff Lang0d8b7242015-09-09 14:56:53 -04001528bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1529{
1530 // List of compressed format that require that the texture size is smaller than or a multiple of
1531 // the compressed block size.
1532 switch (internalFormat)
1533 {
1534 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1535 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1536 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1537 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001538 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001539 return true;
1540
1541 default:
1542 return false;
1543 }
1544}
1545
Jamie Madillc29968b2016-01-20 11:17:23 -05001546bool ValidCompressedImageSize(const ValidationContext *context,
1547 GLenum internalFormat,
1548 GLsizei width,
1549 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001550{
Geoff Lang5d601382014-07-22 15:14:06 -04001551 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1552 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001553 {
1554 return false;
1555 }
1556
Geoff Lang0d8b7242015-09-09 14:56:53 -04001557 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001558 {
1559 return false;
1560 }
1561
Geoff Lang0d8b7242015-09-09 14:56:53 -04001562 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1563 {
1564 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1565 width % formatInfo.compressedBlockWidth != 0) ||
1566 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1567 height % formatInfo.compressedBlockHeight != 0))
1568 {
1569 return false;
1570 }
1571 }
1572
Geoff Langd4f180b2013-09-24 13:57:44 -04001573 return true;
1574}
1575
Geoff Langff5b2d52016-09-07 11:32:23 -04001576bool ValidImageDataSize(ValidationContext *context,
1577 GLenum textureTarget,
1578 GLsizei width,
1579 GLsizei height,
1580 GLsizei depth,
1581 GLenum internalFormat,
1582 GLenum type,
1583 const GLvoid *pixels,
1584 GLsizei imageSize)
1585{
1586 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1587 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1588 {
1589 // Checks are not required
1590 return true;
1591 }
1592
1593 // ...the data would be unpacked from the buffer object such that the memory reads required
1594 // would exceed the data store size.
1595 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1596 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1597 const gl::Extents size(width, height, depth);
1598 const auto &unpack = context->getGLState().getUnpackState();
1599
1600 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1601 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1602 if (endByteOrErr.isError())
1603 {
1604 context->handleError(endByteOrErr.getError());
1605 return false;
1606 }
1607
1608 GLuint endByte = endByteOrErr.getResult();
1609
1610 if (pixelUnpackBuffer)
1611 {
1612 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1613 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1614 checkedEndByte += checkedOffset;
1615
1616 if (!checkedEndByte.IsValid() ||
1617 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1618 {
1619 // Overflow past the end of the buffer
1620 context->handleError(Error(GL_INVALID_OPERATION));
1621 return false;
1622 }
1623 }
1624 else
1625 {
1626 ASSERT(imageSize >= 0);
1627 if (pixels == nullptr && imageSize != 0)
1628 {
1629 context->handleError(
1630 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001631 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001632 }
1633
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001634 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001635 {
1636 context->handleError(
1637 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1638 return false;
1639 }
1640 }
1641
1642 return true;
1643}
1644
Geoff Lang37dde692014-01-31 16:34:54 -05001645bool ValidQueryType(const Context *context, GLenum queryType)
1646{
He Yunchaoced53ae2016-11-29 15:00:51 +08001647 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1648 "GL extension enums not equal.");
1649 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1650 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001651
1652 switch (queryType)
1653 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001654 case GL_ANY_SAMPLES_PASSED:
1655 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1656 return true;
1657 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1658 return (context->getClientMajorVersion() >= 3);
1659 case GL_TIME_ELAPSED_EXT:
1660 return context->getExtensions().disjointTimerQuery;
1661 case GL_COMMANDS_COMPLETED_CHROMIUM:
1662 return context->getExtensions().syncQuery;
1663 default:
1664 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001665 }
1666}
1667
Jamie Madillef300b12016-10-07 15:12:09 -04001668Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001669{
He Yunchaoced53ae2016-11-29 15:00:51 +08001670 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1671 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1672 // or program object and INVALID_OPERATION if the provided name identifies an object
1673 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001674
Dian Xiang769769a2015-09-09 15:20:08 -07001675 Program *validProgram = context->getProgram(id);
1676
1677 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001678 {
Dian Xiang769769a2015-09-09 15:20:08 -07001679 if (context->getShader(id))
1680 {
Jamie Madill437fa652016-05-03 15:13:24 -04001681 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001682 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1683 }
1684 else
1685 {
Jamie Madill437fa652016-05-03 15:13:24 -04001686 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001687 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001688 }
Dian Xiang769769a2015-09-09 15:20:08 -07001689
1690 return validProgram;
1691}
1692
Jamie Madillef300b12016-10-07 15:12:09 -04001693Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001694{
1695 // See ValidProgram for spec details.
1696
1697 Shader *validShader = context->getShader(id);
1698
1699 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001700 {
Dian Xiang769769a2015-09-09 15:20:08 -07001701 if (context->getProgram(id))
1702 {
Jamie Madill437fa652016-05-03 15:13:24 -04001703 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001704 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1705 }
1706 else
1707 {
Jamie Madill437fa652016-05-03 15:13:24 -04001708 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001709 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001710 }
Dian Xiang769769a2015-09-09 15:20:08 -07001711
1712 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001713}
1714
Geoff Langb1196682014-07-23 13:47:29 -04001715bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001716{
1717 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1718 {
1719 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1720
Geoff Langaae65a42014-05-26 12:43:44 -04001721 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001722 {
Jamie Madill437fa652016-05-03 15:13:24 -04001723 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001724 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001725 }
1726 }
1727 else
1728 {
1729 switch (attachment)
1730 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001731 case GL_DEPTH_ATTACHMENT:
1732 case GL_STENCIL_ATTACHMENT:
1733 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001734
He Yunchaoced53ae2016-11-29 15:00:51 +08001735 case GL_DEPTH_STENCIL_ATTACHMENT:
1736 if (!context->getExtensions().webglCompatibility &&
1737 context->getClientMajorVersion() < 3)
1738 {
1739 context->handleError(Error(GL_INVALID_ENUM));
1740 return false;
1741 }
1742 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001743
He Yunchaoced53ae2016-11-29 15:00:51 +08001744 default:
1745 context->handleError(Error(GL_INVALID_ENUM));
1746 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001747 }
1748 }
1749
1750 return true;
1751}
1752
He Yunchaoced53ae2016-11-29 15:00:51 +08001753bool ValidateRenderbufferStorageParametersBase(gl::Context *context,
1754 GLenum target,
1755 GLsizei samples,
1756 GLenum internalformat,
1757 GLsizei width,
1758 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001759{
1760 switch (target)
1761 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001762 case GL_RENDERBUFFER:
1763 break;
1764 default:
1765 context->handleError(Error(GL_INVALID_ENUM));
1766 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001767 }
1768
1769 if (width < 0 || height < 0 || samples < 0)
1770 {
Jamie Madill437fa652016-05-03 15:13:24 -04001771 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001772 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001773 }
1774
Geoff Langd87878e2014-09-19 15:42:59 -04001775 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1776 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001777 {
Jamie Madill437fa652016-05-03 15:13:24 -04001778 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001779 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001780 }
1781
1782 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1783 // 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 -08001784 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001785 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001786 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001787 {
Jamie Madill437fa652016-05-03 15:13:24 -04001788 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001789 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001790 }
1791
Geoff Langaae65a42014-05-26 12:43:44 -04001792 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001793 {
Jamie Madill437fa652016-05-03 15:13:24 -04001794 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001795 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001796 }
1797
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001798 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001799 if (handle == 0)
1800 {
Jamie Madill437fa652016-05-03 15:13:24 -04001801 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001802 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001803 }
1804
1805 return true;
1806}
1807
He Yunchaoced53ae2016-11-29 15:00:51 +08001808bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context,
1809 GLenum target,
1810 GLsizei samples,
1811 GLenum internalformat,
1812 GLsizei width,
1813 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -08001814{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001815 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001816
1817 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001818 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001819 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001820 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001821 {
Jamie Madill437fa652016-05-03 15:13:24 -04001822 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001823 return false;
1824 }
1825
1826 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1827 // the specified storage. This is different than ES 3.0 in which a sample number higher
1828 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001829 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001830 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001831 {
Geoff Langa4903b72015-03-02 16:02:48 -08001832 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1833 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1834 {
Jamie Madill437fa652016-05-03 15:13:24 -04001835 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001836 return false;
1837 }
Corentin Walleze0902642014-11-04 12:32:15 -08001838 }
1839
He Yunchaoced53ae2016-11-29 15:00:51 +08001840 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
1841 width, height);
Corentin Walleze0902642014-11-04 12:32:15 -08001842}
1843
He Yunchaoced53ae2016-11-29 15:00:51 +08001844bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1845 GLenum target,
1846 GLenum attachment,
1847 GLenum renderbuffertarget,
1848 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001849{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001850 if (!ValidFramebufferTarget(target))
1851 {
Jamie Madill437fa652016-05-03 15:13:24 -04001852 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001853 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001854 }
1855
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001856 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001857
Jamie Madill84115c92015-04-23 15:00:07 -04001858 ASSERT(framebuffer);
1859 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001860 {
Jamie Madill437fa652016-05-03 15:13:24 -04001861 context->handleError(
1862 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001863 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001864 }
1865
Jamie Madillb4472272014-07-03 10:38:55 -04001866 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001867 {
Jamie Madillb4472272014-07-03 10:38:55 -04001868 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001869 }
1870
Jamie Madillab9d82c2014-01-21 16:38:14 -05001871 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1872 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1873 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1874 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1875 if (renderbuffer != 0)
1876 {
1877 if (!context->getRenderbuffer(renderbuffer))
1878 {
Jamie Madill437fa652016-05-03 15:13:24 -04001879 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001880 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001881 }
1882 }
1883
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001884 return true;
1885}
1886
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001887bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001888 GLint srcX0,
1889 GLint srcY0,
1890 GLint srcX1,
1891 GLint srcY1,
1892 GLint dstX0,
1893 GLint dstY0,
1894 GLint dstX1,
1895 GLint dstY1,
1896 GLbitfield mask,
1897 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001898{
1899 switch (filter)
1900 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001901 case GL_NEAREST:
1902 break;
1903 case GL_LINEAR:
1904 break;
1905 default:
1906 context->handleError(Error(GL_INVALID_ENUM));
1907 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001908 }
1909
1910 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1911 {
Jamie Madill437fa652016-05-03 15:13:24 -04001912 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001913 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001914 }
1915
1916 if (mask == 0)
1917 {
1918 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1919 // buffers are copied.
1920 return false;
1921 }
1922
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001923 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1924 // color buffer, leaving only nearest being unfiltered from above
1925 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1926 {
Jamie Madill437fa652016-05-03 15:13:24 -04001927 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001928 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001929 }
1930
Jamie Madill51f40ec2016-06-15 14:06:00 -04001931 const auto &glState = context->getGLState();
1932 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1933 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001934
1935 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001936 {
Jamie Madill437fa652016-05-03 15:13:24 -04001937 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001938 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001939 }
1940
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001941 if (readFramebuffer->id() == drawFramebuffer->id())
1942 {
1943 context->handleError(Error(GL_INVALID_OPERATION));
1944 return false;
1945 }
1946
Jamie Madill51f40ec2016-06-15 14:06:00 -04001947 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001948 {
Jamie Madill437fa652016-05-03 15:13:24 -04001949 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001950 return false;
1951 }
1952
Jamie Madill51f40ec2016-06-15 14:06:00 -04001953 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001954 {
Jamie Madill437fa652016-05-03 15:13:24 -04001955 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001956 return false;
1957 }
1958
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001959 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001960 {
Jamie Madill437fa652016-05-03 15:13:24 -04001961 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001962 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001963 }
1964
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001965 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1966
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001967 if (mask & GL_COLOR_BUFFER_BIT)
1968 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001969 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1970 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001971 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001972
1973 if (readColorBuffer && drawColorBuffer)
1974 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001975 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001976
Geoff Langa15472a2015-08-11 11:48:03 -04001977 for (size_t drawbufferIdx = 0;
1978 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001979 {
Geoff Langa15472a2015-08-11 11:48:03 -04001980 const FramebufferAttachment *attachment =
1981 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1982 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001983 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001984 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001985
Geoff Langb2f3d052013-08-13 12:49:27 -04001986 // The GL ES 3.0.2 spec (pg 193) states that:
1987 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001988 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1989 // as well
1990 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1991 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001992 // Changes with EXT_color_buffer_float:
1993 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001994 GLenum readComponentType = readFormat.info->componentType;
1995 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001996 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001997 readComponentType == GL_SIGNED_NORMALIZED);
1998 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1999 drawComponentType == GL_SIGNED_NORMALIZED);
2000
2001 if (extensions.colorBufferFloat)
2002 {
2003 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
2004 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
2005
2006 if (readFixedOrFloat != drawFixedOrFloat)
2007 {
Jamie Madill437fa652016-05-03 15:13:24 -04002008 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002009 "If the read buffer contains fixed-point or "
2010 "floating-point values, the draw buffer "
2011 "must as well."));
2012 return false;
2013 }
2014 }
2015 else if (readFixedPoint != drawFixedPoint)
2016 {
Jamie Madill437fa652016-05-03 15:13:24 -04002017 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002018 "If the read buffer contains fixed-point "
2019 "values, the draw buffer must as well."));
2020 return false;
2021 }
2022
2023 if (readComponentType == GL_UNSIGNED_INT &&
2024 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002025 {
Jamie Madill437fa652016-05-03 15:13:24 -04002026 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002027 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002028 }
2029
Jamie Madill6163c752015-12-07 16:32:59 -05002030 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002031 {
Jamie Madill437fa652016-05-03 15:13:24 -04002032 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002033 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002034 }
2035
Jamie Madilla3944d42016-07-22 22:13:26 -04002036 if (readColorBuffer->getSamples() > 0 &&
2037 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002038 {
Jamie Madill437fa652016-05-03 15:13:24 -04002039 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002040 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002041 }
2042 }
2043 }
2044
Jamie Madilla3944d42016-07-22 22:13:26 -04002045 if ((readFormat.info->componentType == GL_INT ||
2046 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2047 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002048 {
Jamie Madill437fa652016-05-03 15:13:24 -04002049 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002050 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002051 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002052 }
2053 }
2054
He Yunchaoced53ae2016-11-29 15:00:51 +08002055 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002056 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2057 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002058 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002059 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002060 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002061 const gl::FramebufferAttachment *readBuffer =
2062 readFramebuffer->getAttachment(attachments[i]);
2063 const gl::FramebufferAttachment *drawBuffer =
2064 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002065
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002066 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002067 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002068 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002069 {
Jamie Madill437fa652016-05-03 15:13:24 -04002070 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002071 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002072 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002073
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002074 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002075 {
Jamie Madill437fa652016-05-03 15:13:24 -04002076 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002077 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002078 }
2079 }
2080 }
2081 }
2082
2083 return true;
2084}
2085
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002086bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002087 GLint x,
2088 GLint y,
2089 GLsizei width,
2090 GLsizei height,
2091 GLenum format,
2092 GLenum type,
2093 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002094{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002095 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2096}
2097
2098bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2099 GLint x,
2100 GLint y,
2101 GLsizei width,
2102 GLsizei height,
2103 GLenum format,
2104 GLenum type,
2105 GLsizei bufSize,
2106 GLsizei *length,
2107 GLvoid *pixels)
2108{
2109 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002110 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002111 return false;
2112 }
2113
Geoff Lang62fce5b2016-09-30 10:46:35 -04002114 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2115 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002116 {
Geoff Langb1196682014-07-23 13:47:29 -04002117 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002118 }
2119
Geoff Lang62fce5b2016-09-30 10:46:35 -04002120 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002121 {
Geoff Langb1196682014-07-23 13:47:29 -04002122 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002123 }
2124
Jamie Madillc29968b2016-01-20 11:17:23 -05002125 return true;
2126}
2127
2128bool ValidateReadnPixelsEXT(Context *context,
2129 GLint x,
2130 GLint y,
2131 GLsizei width,
2132 GLsizei height,
2133 GLenum format,
2134 GLenum type,
2135 GLsizei bufSize,
2136 GLvoid *pixels)
2137{
2138 if (bufSize < 0)
2139 {
Jamie Madill437fa652016-05-03 15:13:24 -04002140 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002141 return false;
2142 }
2143
Geoff Lang62fce5b2016-09-30 10:46:35 -04002144 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2145 pixels);
2146}
Jamie Madill26e91952014-03-05 15:01:27 -05002147
Geoff Lang62fce5b2016-09-30 10:46:35 -04002148bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2149 GLint x,
2150 GLint y,
2151 GLsizei width,
2152 GLsizei height,
2153 GLenum format,
2154 GLenum type,
2155 GLsizei bufSize,
2156 GLsizei *length,
2157 GLvoid *data)
2158{
2159 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002160 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002161 return false;
2162 }
2163
Geoff Lang62fce5b2016-09-30 10:46:35 -04002164 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002165 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002166 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002167 }
2168
Geoff Lang62fce5b2016-09-30 10:46:35 -04002169 if (!ValidateRobustBufferSize(context, bufSize, *length))
2170 {
2171 return false;
2172 }
2173
2174 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002175}
2176
Olli Etuaho41997e72016-03-10 13:38:39 +02002177bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002178{
2179 if (!context->getExtensions().occlusionQueryBoolean &&
2180 !context->getExtensions().disjointTimerQuery)
2181 {
Jamie Madill437fa652016-05-03 15:13:24 -04002182 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002183 return false;
2184 }
2185
Olli Etuaho41997e72016-03-10 13:38:39 +02002186 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002187}
2188
Olli Etuaho41997e72016-03-10 13:38:39 +02002189bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002190{
2191 if (!context->getExtensions().occlusionQueryBoolean &&
2192 !context->getExtensions().disjointTimerQuery)
2193 {
Jamie Madill437fa652016-05-03 15:13:24 -04002194 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002195 return false;
2196 }
2197
Olli Etuaho41997e72016-03-10 13:38:39 +02002198 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002199}
2200
2201bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002202{
2203 if (!ValidQueryType(context, target))
2204 {
Jamie Madill437fa652016-05-03 15:13:24 -04002205 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002206 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002207 }
2208
2209 if (id == 0)
2210 {
Jamie Madill437fa652016-05-03 15:13:24 -04002211 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002212 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002213 }
2214
2215 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2216 // of zero, if the active query object name for <target> is non-zero (for the
2217 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2218 // the active query for either target is non-zero), if <id> is the name of an
2219 // existing query object whose type does not match <target>, or if <id> is the
2220 // active query object name for any query type, the error INVALID_OPERATION is
2221 // generated.
2222
2223 // Ensure no other queries are active
2224 // NOTE: If other queries than occlusion are supported, we will need to check
2225 // separately that:
2226 // a) The query ID passed is not the current active query for any target/type
2227 // b) There are no active queries for the requested target (and in the case
2228 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2229 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002230
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002231 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002232 {
Jamie Madill437fa652016-05-03 15:13:24 -04002233 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002234 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002235 }
2236
2237 Query *queryObject = context->getQuery(id, true, target);
2238
2239 // check that name was obtained with glGenQueries
2240 if (!queryObject)
2241 {
Jamie Madill437fa652016-05-03 15:13:24 -04002242 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002243 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002244 }
2245
2246 // check for type mismatch
2247 if (queryObject->getType() != target)
2248 {
Jamie Madill437fa652016-05-03 15:13:24 -04002249 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002250 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002251 }
2252
2253 return true;
2254}
2255
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002256bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2257{
2258 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002259 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002260 {
Jamie Madill437fa652016-05-03 15:13:24 -04002261 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002262 return false;
2263 }
2264
2265 return ValidateBeginQueryBase(context, target, id);
2266}
2267
2268bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002269{
2270 if (!ValidQueryType(context, target))
2271 {
Jamie Madill437fa652016-05-03 15:13:24 -04002272 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002273 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002274 }
2275
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002276 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002277
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002278 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002279 {
Jamie Madill437fa652016-05-03 15:13:24 -04002280 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002281 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002282 }
2283
Jamie Madill45c785d2014-05-13 14:09:34 -04002284 return true;
2285}
2286
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002287bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2288{
2289 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002290 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002291 {
Jamie Madill437fa652016-05-03 15:13:24 -04002292 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002293 return false;
2294 }
2295
2296 return ValidateEndQueryBase(context, target);
2297}
2298
2299bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2300{
2301 if (!context->getExtensions().disjointTimerQuery)
2302 {
Jamie Madill437fa652016-05-03 15:13:24 -04002303 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002304 return false;
2305 }
2306
2307 if (target != GL_TIMESTAMP_EXT)
2308 {
Jamie Madill437fa652016-05-03 15:13:24 -04002309 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002310 return false;
2311 }
2312
2313 Query *queryObject = context->getQuery(id, true, target);
2314 if (queryObject == nullptr)
2315 {
Jamie Madill437fa652016-05-03 15:13:24 -04002316 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002317 return false;
2318 }
2319
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002320 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002321 {
Jamie Madill437fa652016-05-03 15:13:24 -04002322 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002323 return false;
2324 }
2325
2326 return true;
2327}
2328
Geoff Lang2186c382016-10-14 10:54:54 -04002329bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002330{
Geoff Lang2186c382016-10-14 10:54:54 -04002331 if (numParams)
2332 {
2333 *numParams = 0;
2334 }
2335
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002336 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2337 {
Jamie Madill437fa652016-05-03 15:13:24 -04002338 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002339 return false;
2340 }
2341
2342 switch (pname)
2343 {
2344 case GL_CURRENT_QUERY_EXT:
2345 if (target == GL_TIMESTAMP_EXT)
2346 {
Jamie Madill437fa652016-05-03 15:13:24 -04002347 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002348 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2349 return false;
2350 }
2351 break;
2352 case GL_QUERY_COUNTER_BITS_EXT:
2353 if (!context->getExtensions().disjointTimerQuery ||
2354 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2355 {
Jamie Madill437fa652016-05-03 15:13:24 -04002356 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002357 return false;
2358 }
2359 break;
2360 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002361 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002362 return false;
2363 }
2364
Geoff Lang2186c382016-10-14 10:54:54 -04002365 if (numParams)
2366 {
2367 // All queries return only one value
2368 *numParams = 1;
2369 }
2370
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002371 return true;
2372}
2373
2374bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2375{
2376 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002377 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002378 {
Jamie Madill437fa652016-05-03 15:13:24 -04002379 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002380 return false;
2381 }
2382
Geoff Lang2186c382016-10-14 10:54:54 -04002383 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002384}
2385
Geoff Lang2186c382016-10-14 10:54:54 -04002386bool ValidateGetQueryivRobustANGLE(Context *context,
2387 GLenum target,
2388 GLenum pname,
2389 GLsizei bufSize,
2390 GLsizei *length,
2391 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002392{
Geoff Lang2186c382016-10-14 10:54:54 -04002393 if (!ValidateRobustEntryPoint(context, bufSize))
2394 {
2395 return false;
2396 }
2397
2398 if (!ValidateGetQueryivBase(context, target, pname, length))
2399 {
2400 return false;
2401 }
2402
2403 if (!ValidateRobustBufferSize(context, bufSize, *length))
2404 {
2405 return false;
2406 }
2407
2408 return true;
2409}
2410
2411bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2412{
2413 if (numParams)
2414 {
2415 *numParams = 0;
2416 }
2417
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002418 Query *queryObject = context->getQuery(id, false, GL_NONE);
2419
2420 if (!queryObject)
2421 {
Jamie Madill437fa652016-05-03 15:13:24 -04002422 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002423 return false;
2424 }
2425
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002426 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002427 {
Jamie Madill437fa652016-05-03 15:13:24 -04002428 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002429 return false;
2430 }
2431
2432 switch (pname)
2433 {
2434 case GL_QUERY_RESULT_EXT:
2435 case GL_QUERY_RESULT_AVAILABLE_EXT:
2436 break;
2437
2438 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002439 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002440 return false;
2441 }
2442
Geoff Lang2186c382016-10-14 10:54:54 -04002443 if (numParams)
2444 {
2445 *numParams = 1;
2446 }
2447
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002448 return true;
2449}
2450
2451bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2452{
2453 if (!context->getExtensions().disjointTimerQuery)
2454 {
Jamie Madill437fa652016-05-03 15:13:24 -04002455 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002456 return false;
2457 }
Geoff Lang2186c382016-10-14 10:54:54 -04002458 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2459}
2460
2461bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2462 GLuint id,
2463 GLenum pname,
2464 GLsizei bufSize,
2465 GLsizei *length,
2466 GLint *params)
2467{
2468 if (!context->getExtensions().disjointTimerQuery)
2469 {
2470 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2471 return false;
2472 }
2473
2474 if (!ValidateRobustEntryPoint(context, bufSize))
2475 {
2476 return false;
2477 }
2478
2479 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2480 {
2481 return false;
2482 }
2483
2484 if (!ValidateRobustBufferSize(context, bufSize, *length))
2485 {
2486 return false;
2487 }
2488
2489 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002490}
2491
2492bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2493{
2494 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002495 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002496 {
Jamie Madill437fa652016-05-03 15:13:24 -04002497 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002498 return false;
2499 }
Geoff Lang2186c382016-10-14 10:54:54 -04002500 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2501}
2502
2503bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2504 GLuint id,
2505 GLenum pname,
2506 GLsizei bufSize,
2507 GLsizei *length,
2508 GLuint *params)
2509{
2510 if (!context->getExtensions().disjointTimerQuery &&
2511 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2512 {
2513 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2514 return false;
2515 }
2516
2517 if (!ValidateRobustEntryPoint(context, bufSize))
2518 {
2519 return false;
2520 }
2521
2522 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2523 {
2524 return false;
2525 }
2526
2527 if (!ValidateRobustBufferSize(context, bufSize, *length))
2528 {
2529 return false;
2530 }
2531
2532 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002533}
2534
2535bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2536{
2537 if (!context->getExtensions().disjointTimerQuery)
2538 {
Jamie Madill437fa652016-05-03 15:13:24 -04002539 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002540 return false;
2541 }
Geoff Lang2186c382016-10-14 10:54:54 -04002542 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2543}
2544
2545bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2546 GLuint id,
2547 GLenum pname,
2548 GLsizei bufSize,
2549 GLsizei *length,
2550 GLint64 *params)
2551{
2552 if (!context->getExtensions().disjointTimerQuery)
2553 {
2554 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2555 return false;
2556 }
2557
2558 if (!ValidateRobustEntryPoint(context, bufSize))
2559 {
2560 return false;
2561 }
2562
2563 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2564 {
2565 return false;
2566 }
2567
2568 if (!ValidateRobustBufferSize(context, bufSize, *length))
2569 {
2570 return false;
2571 }
2572
2573 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002574}
2575
2576bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2577{
2578 if (!context->getExtensions().disjointTimerQuery)
2579 {
Jamie Madill437fa652016-05-03 15:13:24 -04002580 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002581 return false;
2582 }
Geoff Lang2186c382016-10-14 10:54:54 -04002583 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2584}
2585
2586bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2587 GLuint id,
2588 GLenum pname,
2589 GLsizei bufSize,
2590 GLsizei *length,
2591 GLuint64 *params)
2592{
2593 if (!context->getExtensions().disjointTimerQuery)
2594 {
2595 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2596 return false;
2597 }
2598
2599 if (!ValidateRobustEntryPoint(context, bufSize))
2600 {
2601 return false;
2602 }
2603
2604 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2605 {
2606 return false;
2607 }
2608
2609 if (!ValidateRobustBufferSize(context, bufSize, *length))
2610 {
2611 return false;
2612 }
2613
2614 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002615}
2616
Jamie Madill62d31cb2015-09-11 13:25:51 -04002617static bool ValidateUniformCommonBase(gl::Context *context,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002618 gl::Program *program,
Jamie Madill62d31cb2015-09-11 13:25:51 -04002619 GLenum targetUniformType,
2620 GLint location,
2621 GLsizei count,
2622 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002623{
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002624 // TODO(Jiajia): Add image uniform check in future.
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002625 if (count < 0)
2626 {
Jamie Madill437fa652016-05-03 15:13:24 -04002627 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002628 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002629 }
2630
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002631 if (!program || !program->isLinked())
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002632 {
Jamie Madill437fa652016-05-03 15:13:24 -04002633 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002634 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002635 }
2636
Geoff Langd8605522016-04-13 10:19:12 -04002637 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002638 {
2639 // Silently ignore the uniform command
2640 return false;
2641 }
2642
Geoff Lang7dd2e102014-11-10 15:19:26 -05002643 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002644 {
Jamie Madill437fa652016-05-03 15:13:24 -04002645 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002646 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002647 }
2648
Jamie Madill62d31cb2015-09-11 13:25:51 -04002649 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002650
2651 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002652 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002653 {
Jamie Madill437fa652016-05-03 15:13:24 -04002654 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002655 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002656 }
2657
Jamie Madill62d31cb2015-09-11 13:25:51 -04002658 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002659 return true;
2660}
2661
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002662bool ValidateProgramUniform(gl::Context *context,
2663 GLenum uniformType,
2664 GLuint program,
2665 GLint location,
2666 GLsizei count)
2667{
2668 // Check for ES31 program uniform entry points
2669 if (context->getClientVersion() < Version(3, 1))
2670 {
2671 context->handleError(Error(GL_INVALID_OPERATION));
2672 return false;
2673 }
2674
2675 const LinkedUniform *uniform = nullptr;
2676 gl::Program *programObject = GetValidProgram(context, program);
2677 if (!ValidateUniformCommonBase(context, programObject, uniformType, location, count, &uniform))
2678 {
2679 return false;
2680 }
2681
2682 GLenum targetBoolType = VariableBoolVectorType(uniformType);
2683 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
2684 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2685 {
2686 context->handleError(Error(GL_INVALID_OPERATION));
2687 return false;
2688 }
2689
2690 return true;
2691}
2692
2693bool ValidateProgramUniformMatrix(gl::Context *context,
2694 GLenum matrixType,
2695 GLuint program,
2696 GLint location,
2697 GLsizei count,
2698 GLboolean transpose)
2699{
2700 // Check for ES31 program uniform entry points
2701 if (context->getClientVersion() < Version(3, 1))
2702 {
2703 context->handleError(Error(GL_INVALID_OPERATION));
2704 return false;
2705 }
2706
2707 const LinkedUniform *uniform = nullptr;
2708 gl::Program *programObject = GetValidProgram(context, program);
2709 if (!ValidateUniformCommonBase(context, programObject, matrixType, location, count, &uniform))
2710 {
2711 return false;
2712 }
2713
2714 if (uniform->type != matrixType)
2715 {
2716 context->handleError(Error(GL_INVALID_OPERATION));
2717 return false;
2718 }
2719
2720 return true;
2721}
2722
Jamie Madillaa981bd2014-05-20 10:55:55 -04002723bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2724{
2725 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002726 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2727 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002728 {
Jamie Madill437fa652016-05-03 15:13:24 -04002729 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002730 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002731 }
2732
Jamie Madill62d31cb2015-09-11 13:25:51 -04002733 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002734 gl::Program *program = context->getGLState().getProgram();
2735 if (!ValidateUniformCommonBase(context, program, uniformType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002736 {
2737 return false;
2738 }
2739
He Yunchaoced53ae2016-11-29 15:00:51 +08002740 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002741 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002742 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2743 {
Jamie Madill437fa652016-05-03 15:13:24 -04002744 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002745 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002746 }
2747
2748 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002749}
2750
He Yunchaoced53ae2016-11-29 15:00:51 +08002751bool ValidateUniformMatrix(gl::Context *context,
2752 GLenum matrixType,
2753 GLint location,
2754 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002755 GLboolean transpose)
2756{
2757 // Check for ES3 uniform entry points
2758 int rows = VariableRowCount(matrixType);
2759 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002760 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002761 {
Jamie Madill437fa652016-05-03 15:13:24 -04002762 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002763 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002764 }
2765
Martin Radev1be913c2016-07-11 17:59:16 +03002766 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002767 {
Jamie Madill437fa652016-05-03 15:13:24 -04002768 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002769 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002770 }
2771
Jamie Madill62d31cb2015-09-11 13:25:51 -04002772 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002773 gl::Program *program = context->getGLState().getProgram();
2774 if (!ValidateUniformCommonBase(context, program, matrixType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002775 {
2776 return false;
2777 }
2778
2779 if (uniform->type != matrixType)
2780 {
Jamie Madill437fa652016-05-03 15:13:24 -04002781 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002782 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002783 }
2784
2785 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002786}
2787
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002788bool ValidateStateQuery(ValidationContext *context,
2789 GLenum pname,
2790 GLenum *nativeType,
2791 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002792{
2793 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2794 {
Jamie Madill437fa652016-05-03 15:13:24 -04002795 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002796 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002797 }
2798
Jamie Madill0af26e12015-03-05 19:54:33 -05002799 const Caps &caps = context->getCaps();
2800
Jamie Madill893ab082014-05-16 16:56:10 -04002801 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2802 {
2803 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2804
Jamie Madill0af26e12015-03-05 19:54:33 -05002805 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002806 {
Jamie Madill437fa652016-05-03 15:13:24 -04002807 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002808 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002809 }
2810 }
2811
2812 switch (pname)
2813 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002814 case GL_TEXTURE_BINDING_2D:
2815 case GL_TEXTURE_BINDING_CUBE_MAP:
2816 case GL_TEXTURE_BINDING_3D:
2817 case GL_TEXTURE_BINDING_2D_ARRAY:
2818 break;
2819 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2820 if (!context->getExtensions().eglStreamConsumerExternal &&
2821 !context->getExtensions().eglImageExternal)
2822 {
2823 context->handleError(Error(GL_INVALID_ENUM,
2824 "Neither NV_EGL_stream_consumer_external nor "
2825 "GL_OES_EGL_image_external extensions enabled"));
2826 return false;
2827 }
2828 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002829
He Yunchaoced53ae2016-11-29 15:00:51 +08002830 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2831 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002832 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002833 if (context->getGLState().getReadFramebuffer()->checkStatus(
2834 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002835 {
Jamie Madill437fa652016-05-03 15:13:24 -04002836 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002837 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002838 }
2839
Jamie Madill51f40ec2016-06-15 14:06:00 -04002840 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2841 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002842
2843 if (framebuffer->getReadBufferState() == GL_NONE)
2844 {
2845 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2846 return false;
2847 }
2848
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002849 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002850 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002851 {
Jamie Madill437fa652016-05-03 15:13:24 -04002852 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002853 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002854 }
2855 }
2856 break;
2857
He Yunchaoced53ae2016-11-29 15:00:51 +08002858 default:
2859 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002860 }
2861
2862 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002863 if (*numParams == 0)
2864 {
2865 return false;
2866 }
2867
2868 return true;
2869}
2870
2871bool ValidateRobustStateQuery(ValidationContext *context,
2872 GLenum pname,
2873 GLsizei bufSize,
2874 GLenum *nativeType,
2875 unsigned int *numParams)
2876{
2877 if (!ValidateRobustEntryPoint(context, bufSize))
2878 {
2879 return false;
2880 }
2881
2882 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2883 {
2884 return false;
2885 }
2886
2887 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002888 {
2889 return false;
2890 }
2891
2892 return true;
2893}
2894
Jamie Madillc29968b2016-01-20 11:17:23 -05002895bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2896 GLenum target,
2897 GLint level,
2898 GLenum internalformat,
2899 bool isSubImage,
2900 GLint xoffset,
2901 GLint yoffset,
2902 GLint zoffset,
2903 GLint x,
2904 GLint y,
2905 GLsizei width,
2906 GLsizei height,
2907 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002908 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002909{
Jamie Madill560a8d82014-05-21 13:06:20 -04002910 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2911 {
Jamie Madill437fa652016-05-03 15:13:24 -04002912 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002913 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002914 }
2915
He Yunchaoced53ae2016-11-29 15:00:51 +08002916 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2917 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002918 {
Jamie Madill437fa652016-05-03 15:13:24 -04002919 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002920 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002921 }
2922
2923 if (border != 0)
2924 {
Jamie Madill437fa652016-05-03 15:13:24 -04002925 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002926 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002927 }
2928
2929 if (!ValidMipLevel(context, target, level))
2930 {
Jamie Madill437fa652016-05-03 15:13:24 -04002931 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002932 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002933 }
2934
Jamie Madill51f40ec2016-06-15 14:06:00 -04002935 const auto &state = context->getGLState();
2936 auto readFramebuffer = state.getReadFramebuffer();
2937 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002938 {
Jamie Madill437fa652016-05-03 15:13:24 -04002939 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002940 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002941 }
2942
Jamie Madill51f40ec2016-06-15 14:06:00 -04002943 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002944 {
Jamie Madill437fa652016-05-03 15:13:24 -04002945 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002946 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002947 }
2948
Martin Radev138064f2016-07-15 12:03:41 +03002949 if (readFramebuffer->getReadBufferState() == GL_NONE)
2950 {
2951 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2952 return false;
2953 }
2954
Geoff Langaae65a42014-05-26 12:43:44 -04002955 const gl::Caps &caps = context->getCaps();
2956
Geoff Langaae65a42014-05-26 12:43:44 -04002957 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002958 switch (target)
2959 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002960 case GL_TEXTURE_2D:
2961 maxDimension = caps.max2DTextureSize;
2962 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002963
He Yunchaoced53ae2016-11-29 15:00:51 +08002964 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2965 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2966 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2967 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2968 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2969 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2970 maxDimension = caps.maxCubeMapTextureSize;
2971 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002972
He Yunchaoced53ae2016-11-29 15:00:51 +08002973 case GL_TEXTURE_2D_ARRAY:
2974 maxDimension = caps.max2DTextureSize;
2975 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002976
He Yunchaoced53ae2016-11-29 15:00:51 +08002977 case GL_TEXTURE_3D:
2978 maxDimension = caps.max3DTextureSize;
2979 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002980
He Yunchaoced53ae2016-11-29 15:00:51 +08002981 default:
2982 context->handleError(Error(GL_INVALID_ENUM));
2983 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002984 }
2985
Jamie Madillc29968b2016-01-20 11:17:23 -05002986 gl::Texture *texture =
2987 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002988 if (!texture)
2989 {
Jamie Madill437fa652016-05-03 15:13:24 -04002990 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002991 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002992 }
2993
Geoff Lang69cce582015-09-17 13:20:36 -04002994 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002995 {
Jamie Madill437fa652016-05-03 15:13:24 -04002996 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002997 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002998 }
2999
Geoff Lang5d601382014-07-22 15:14:06 -04003000 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
3001
3002 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04003003 {
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 Langa9be0dc2014-12-17 12:34:40 -05003008 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04003009 {
Jamie Madill437fa652016-05-03 15:13:24 -04003010 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003011 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003012 }
3013
3014 if (isSubImage)
3015 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003016 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3017 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3018 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003019 {
Jamie Madill437fa652016-05-03 15:13:24 -04003020 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003021 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003022 }
3023 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003024 else
3025 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003026 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003027 {
Jamie Madill437fa652016-05-03 15:13:24 -04003028 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003029 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003030 }
3031
Geoff Langeb66a6e2016-10-31 13:06:12 -04003032 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003033 {
Jamie Madill437fa652016-05-03 15:13:24 -04003034 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003035 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003036 }
3037
3038 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003039 if (static_cast<int>(width) > maxLevelDimension ||
3040 static_cast<int>(height) > maxLevelDimension)
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 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003046
Jamie Madill0c8abca2016-07-22 20:21:26 -04003047 if (textureFormatOut)
3048 {
3049 *textureFormatOut = texture->getFormat(target, level);
3050 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003051 return true;
3052}
3053
Jamie Madillf25855c2015-11-03 11:06:18 -05003054static bool ValidateDrawBase(ValidationContext *context,
3055 GLenum mode,
3056 GLsizei count,
3057 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003058{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003059 switch (mode)
3060 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003061 case GL_POINTS:
3062 case GL_LINES:
3063 case GL_LINE_LOOP:
3064 case GL_LINE_STRIP:
3065 case GL_TRIANGLES:
3066 case GL_TRIANGLE_STRIP:
3067 case GL_TRIANGLE_FAN:
3068 break;
3069 default:
3070 context->handleError(Error(GL_INVALID_ENUM));
3071 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003072 }
3073
Jamie Madill250d33f2014-06-06 17:09:03 -04003074 if (count < 0)
3075 {
Jamie Madill437fa652016-05-03 15:13:24 -04003076 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003077 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003078 }
3079
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003080 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003081
Jamie Madill250d33f2014-06-06 17:09:03 -04003082 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003083 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003084 {
Jamie Madill437fa652016-05-03 15:13:24 -04003085 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003086 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003087 }
3088
Jamie Madill51f40ec2016-06-15 14:06:00 -04003089 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04003090 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04003091 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04003092 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
He Yunchaoced53ae2016-11-29 15:00:51 +08003093 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
3094 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003095 const DepthStencilState &depthStencilState = state.getDepthStencilState();
3096 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3097 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04003098 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04003099 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3100 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04003101 {
3102 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3103 // Section 6.10 of the WebGL 1.0 spec
He Yunchaoced53ae2016-11-29 15:00:51 +08003104 ERR("This ANGLE implementation does not support separate front/back stencil "
Geoff Lang3a86ad32015-09-01 11:47:05 -04003105 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04003106 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003107 return false;
3108 }
Jamie Madillac528012014-06-20 13:21:23 -04003109 }
3110
Jamie Madill51f40ec2016-06-15 14:06:00 -04003111 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003112 {
Jamie Madill437fa652016-05-03 15:13:24 -04003113 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003114 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003115 }
3116
Geoff Lang7dd2e102014-11-10 15:19:26 -05003117 gl::Program *program = state.getProgram();
3118 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003119 {
Jamie Madill437fa652016-05-03 15:13:24 -04003120 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003121 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003122 }
3123
Geoff Lang7dd2e102014-11-10 15:19:26 -05003124 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003125 {
Jamie Madill437fa652016-05-03 15:13:24 -04003126 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003127 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003128 }
3129
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003130 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003131 for (unsigned int uniformBlockIndex = 0;
3132 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003133 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003134 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003135 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003136 const OffsetBindingPointer<Buffer> &uniformBuffer =
3137 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003138
Geoff Lang5d124a62015-09-15 13:03:27 -04003139 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003140 {
3141 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003142 context->handleError(
3143 Error(GL_INVALID_OPERATION,
3144 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003145 return false;
3146 }
3147
Geoff Lang5d124a62015-09-15 13:03:27 -04003148 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003149 if (uniformBufferSize == 0)
3150 {
3151 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003152 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003153 }
3154
Jamie Madill62d31cb2015-09-11 13:25:51 -04003155 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003156 {
3157 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003158 context->handleError(
3159 Error(GL_INVALID_OPERATION,
3160 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003161 return false;
3162 }
3163 }
3164
Jamie Madill250d33f2014-06-06 17:09:03 -04003165 // No-op if zero count
3166 return (count > 0);
3167}
3168
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003169bool ValidateDrawArrays(ValidationContext *context,
3170 GLenum mode,
3171 GLint first,
3172 GLsizei count,
3173 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003174{
Jamie Madillfd716582014-06-06 17:09:04 -04003175 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003176 {
Jamie Madill437fa652016-05-03 15:13:24 -04003177 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003178 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003179 }
3180
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003181 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003182 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003183 if (curTransformFeedback && curTransformFeedback->isActive() &&
3184 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003185 {
3186 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003187 // that does not match the current transform feedback object's draw mode (if transform
3188 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003189 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003190 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003191 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003192 }
3193
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003194 if (!ValidateDrawBase(context, mode, count, primcount))
3195 {
3196 return false;
3197 }
3198
Corentin Wallez92db6942016-12-09 13:10:36 -05003199 CheckedNumeric<GLint> maxVertex = first;
3200 maxVertex += count;
3201 maxVertex -= 1;
3202
3203 if (!maxVertex.IsValid())
3204 {
3205 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3206 return false;
3207 }
3208
3209 if (!ValidateDrawAttribs(context, primcount, maxVertex.ValueOrDie(), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003210 {
3211 return false;
3212 }
3213
3214 return true;
3215}
3216
He Yunchaoced53ae2016-11-29 15:00:51 +08003217bool ValidateDrawArraysInstanced(Context *context,
3218 GLenum mode,
3219 GLint first,
3220 GLsizei count,
3221 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003222{
3223 if (primcount < 0)
3224 {
Jamie Madill437fa652016-05-03 15:13:24 -04003225 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003226 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003227 }
3228
Jamie Madill2b976812014-08-25 15:47:49 -04003229 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003230 {
3231 return false;
3232 }
3233
3234 // No-op if zero primitive count
3235 return (primcount > 0);
3236}
3237
Geoff Lang87a93302014-09-16 13:29:43 -04003238static bool ValidateDrawInstancedANGLE(Context *context)
3239{
3240 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003241 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003242
Geoff Lang7dd2e102014-11-10 15:19:26 -05003243 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003244
3245 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003246 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003247 {
3248 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003249 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003250 {
3251 return true;
3252 }
3253 }
3254
Jamie Madill437fa652016-05-03 15:13:24 -04003255 context->handleError(Error(GL_INVALID_OPERATION,
3256 "ANGLE_instanced_arrays requires that at least one active attribute"
3257 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003258 return false;
3259}
3260
He Yunchaoced53ae2016-11-29 15:00:51 +08003261bool ValidateDrawArraysInstancedANGLE(Context *context,
3262 GLenum mode,
3263 GLint first,
3264 GLsizei count,
3265 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003266{
3267 if (!ValidateDrawInstancedANGLE(context))
3268 {
3269 return false;
3270 }
3271
3272 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3273}
3274
Jamie Madillf25855c2015-11-03 11:06:18 -05003275bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003276 GLenum mode,
3277 GLsizei count,
3278 GLenum type,
3279 const GLvoid *indices,
3280 GLsizei primcount,
3281 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003282{
Jamie Madill250d33f2014-06-06 17:09:03 -04003283 switch (type)
3284 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003285 case GL_UNSIGNED_BYTE:
3286 case GL_UNSIGNED_SHORT:
3287 break;
3288 case GL_UNSIGNED_INT:
3289 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3290 {
3291 context->handleError(Error(GL_INVALID_ENUM));
3292 return false;
3293 }
3294 break;
3295 default:
3296 context->handleError(Error(GL_INVALID_ENUM));
3297 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003298 }
3299
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003300 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003301
3302 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003303 if (curTransformFeedback && curTransformFeedback->isActive() &&
3304 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003305 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003306 // It is an invalid operation to call DrawElements, DrawRangeElements or
3307 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003308 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003309 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003310 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003311 }
3312
3313 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003314 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003315 {
Jamie Madill437fa652016-05-03 15:13:24 -04003316 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003317 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003318 }
3319
He Yunchaoced53ae2016-11-29 15:00:51 +08003320 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003321 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003322
Jamie Madillae3000b2014-08-25 15:47:51 -04003323 if (elementArrayBuffer)
3324 {
3325 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3326
3327 GLint64 offset = reinterpret_cast<GLint64>(indices);
He Yunchaoced53ae2016-11-29 15:00:51 +08003328 GLint64 byteCount =
3329 static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count) + offset;
Jamie Madillae3000b2014-08-25 15:47:51 -04003330
3331 // check for integer overflows
3332 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3333 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3334 {
Jamie Madill437fa652016-05-03 15:13:24 -04003335 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003336 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003337 }
3338
3339 // Check for reading past the end of the bound buffer object
3340 if (byteCount > elementArrayBuffer->getSize())
3341 {
Jamie Madill437fa652016-05-03 15:13:24 -04003342 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003343 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003344 }
3345 }
Corentin Wallez327411e2016-12-09 11:09:17 -05003346 else if (context->getExtensions().webglCompatibility && count > 0)
3347 {
3348 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3349 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3350 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
3351 context->handleError(
3352 Error(GL_INVALID_OPERATION, "There is no element array buffer bound and count > 0."));
3353 return false;
3354 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003355 else if (!indices)
3356 {
Corentin Wallez327411e2016-12-09 11:09:17 -05003357 // This is an application error that would normally result in a crash,
3358 // but we catch it and return an error
3359 context->handleError(
3360 Error(GL_INVALID_OPERATION, "No element array buffer and no pointer."));
Geoff Langb1196682014-07-23 13:47:29 -04003361 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003362 }
3363
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003364 if (!ValidateDrawBase(context, mode, count, primcount))
3365 {
3366 return false;
3367 }
3368
Jamie Madill2b976812014-08-25 15:47:49 -04003369 // Use max index to validate if our vertex buffers are large enough for the pull.
3370 // TODO: offer fast path, with disabled index validation.
3371 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3372 if (elementArrayBuffer)
3373 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003374 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003375 Error error =
3376 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3377 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003378 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003379 {
Jamie Madill437fa652016-05-03 15:13:24 -04003380 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003381 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003382 }
3383 }
3384 else
3385 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003386 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003387 }
3388
Jamie Madille79b1e12015-11-04 16:36:37 -05003389 // If we use an index greater than our maximum supported index range, return an error.
3390 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3391 // return an error if possible here.
3392 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3393 {
Jamie Madill437fa652016-05-03 15:13:24 -04003394 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003395 return false;
3396 }
3397
Corentin Wallez92db6942016-12-09 13:10:36 -05003398 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3399 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003400 {
3401 return false;
3402 }
3403
Geoff Lang3edfe032015-09-04 16:38:24 -04003404 // No op if there are no real indices in the index data (all are primitive restart).
3405 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003406}
3407
Geoff Langb1196682014-07-23 13:47:29 -04003408bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003409 GLenum mode,
3410 GLsizei count,
3411 GLenum type,
3412 const GLvoid *indices,
3413 GLsizei primcount,
3414 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003415{
3416 if (primcount < 0)
3417 {
Jamie Madill437fa652016-05-03 15:13:24 -04003418 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003419 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003420 }
3421
Jamie Madill2b976812014-08-25 15:47:49 -04003422 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003423 {
3424 return false;
3425 }
3426
3427 // No-op zero primitive count
3428 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003429}
3430
Geoff Lang3edfe032015-09-04 16:38:24 -04003431bool ValidateDrawElementsInstancedANGLE(Context *context,
3432 GLenum mode,
3433 GLsizei count,
3434 GLenum type,
3435 const GLvoid *indices,
3436 GLsizei primcount,
3437 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003438{
3439 if (!ValidateDrawInstancedANGLE(context))
3440 {
3441 return false;
3442 }
3443
He Yunchaoced53ae2016-11-29 15:00:51 +08003444 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3445 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003446}
3447
He Yunchaoced53ae2016-11-29 15:00:51 +08003448bool ValidateFramebufferTextureBase(Context *context,
3449 GLenum target,
3450 GLenum attachment,
3451 GLuint texture,
3452 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003453{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003454 if (!ValidFramebufferTarget(target))
3455 {
Jamie Madill437fa652016-05-03 15:13:24 -04003456 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003457 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003458 }
3459
3460 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003461 {
3462 return false;
3463 }
3464
Jamie Madill55ec3b12014-07-03 10:38:57 -04003465 if (texture != 0)
3466 {
3467 gl::Texture *tex = context->getTexture(texture);
3468
3469 if (tex == NULL)
3470 {
Jamie Madill437fa652016-05-03 15:13:24 -04003471 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003472 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003473 }
3474
3475 if (level < 0)
3476 {
Jamie Madill437fa652016-05-03 15:13:24 -04003477 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003478 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003479 }
3480 }
3481
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003482 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003483 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003484
Jamie Madill84115c92015-04-23 15:00:07 -04003485 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003486 {
Jamie Madill437fa652016-05-03 15:13:24 -04003487 context->handleError(
3488 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003489 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003490 }
3491
3492 return true;
3493}
3494
He Yunchaoced53ae2016-11-29 15:00:51 +08003495bool ValidateFramebufferTexture2D(Context *context,
3496 GLenum target,
3497 GLenum attachment,
3498 GLenum textarget,
3499 GLuint texture,
3500 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003501{
He Yunchaoced53ae2016-11-29 15:00:51 +08003502 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3503 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003504 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3505 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003506 {
Jamie Madill437fa652016-05-03 15:13:24 -04003507 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003508 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003509 }
3510
3511 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003512 {
3513 return false;
3514 }
3515
Jamie Madill55ec3b12014-07-03 10:38:57 -04003516 if (texture != 0)
3517 {
3518 gl::Texture *tex = context->getTexture(texture);
3519 ASSERT(tex);
3520
Jamie Madill2a6564e2014-07-11 09:53:19 -04003521 const gl::Caps &caps = context->getCaps();
3522
Jamie Madill55ec3b12014-07-03 10:38:57 -04003523 switch (textarget)
3524 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003525 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003526 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003527 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003528 {
Jamie Madill437fa652016-05-03 15:13:24 -04003529 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003530 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003531 }
3532 if (tex->getTarget() != GL_TEXTURE_2D)
3533 {
Jamie Madill437fa652016-05-03 15:13:24 -04003534 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003535 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003536 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003537 }
3538 break;
3539
He Yunchaoced53ae2016-11-29 15:00:51 +08003540 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3541 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3542 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3543 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3544 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3545 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003546 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003547 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003548 {
Jamie Madill437fa652016-05-03 15:13:24 -04003549 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003550 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003551 }
3552 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3553 {
Jamie Madill437fa652016-05-03 15:13:24 -04003554 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003555 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003556 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003557 }
3558 break;
3559
He Yunchaoced53ae2016-11-29 15:00:51 +08003560 default:
3561 context->handleError(Error(GL_INVALID_ENUM));
3562 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003563 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003564
Jamie Madilla3944d42016-07-22 22:13:26 -04003565 const Format &format = tex->getFormat(textarget, level);
3566 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003567 {
Jamie Madill437fa652016-05-03 15:13:24 -04003568 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003569 return false;
3570 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003571 }
3572
Jamie Madill570f7c82014-07-03 10:38:54 -04003573 return true;
3574}
3575
Geoff Langb1196682014-07-23 13:47:29 -04003576bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003577{
3578 if (program == 0)
3579 {
Jamie Madill437fa652016-05-03 15:13:24 -04003580 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003581 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003582 }
3583
Dian Xiang769769a2015-09-09 15:20:08 -07003584 gl::Program *programObject = GetValidProgram(context, program);
3585 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003586 {
3587 return false;
3588 }
3589
Jamie Madill0063c512014-08-25 15:47:53 -04003590 if (!programObject || !programObject->isLinked())
3591 {
Jamie Madill437fa652016-05-03 15:13:24 -04003592 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003593 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003594 }
3595
Geoff Lang7dd2e102014-11-10 15:19:26 -05003596 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003597 {
Jamie Madill437fa652016-05-03 15:13:24 -04003598 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003599 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003600 }
3601
Jamie Madill0063c512014-08-25 15:47:53 -04003602 return true;
3603}
3604
He Yunchaoced53ae2016-11-29 15:00:51 +08003605bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003606{
3607 return ValidateGetUniformBase(context, program, location);
3608}
3609
He Yunchaoced53ae2016-11-29 15:00:51 +08003610bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003611{
Jamie Madill78f41802014-08-25 15:47:55 -04003612 return ValidateGetUniformBase(context, program, location);
3613}
3614
Geoff Langf41d0ee2016-10-07 13:04:23 -04003615static bool ValidateSizedGetUniform(Context *context,
3616 GLuint program,
3617 GLint location,
3618 GLsizei bufSize,
3619 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003620{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003621 if (length)
3622 {
3623 *length = 0;
3624 }
3625
Jamie Madill78f41802014-08-25 15:47:55 -04003626 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003627 {
Jamie Madill78f41802014-08-25 15:47:55 -04003628 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003629 }
3630
Geoff Langf41d0ee2016-10-07 13:04:23 -04003631 if (bufSize < 0)
3632 {
3633 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3634 return false;
3635 }
3636
Jamie Madilla502c742014-08-28 17:19:13 -04003637 gl::Program *programObject = context->getProgram(program);
3638 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003639
Jamie Madill78f41802014-08-25 15:47:55 -04003640 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003641 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003642 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003643 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003644 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003645 context->handleError(
3646 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003647 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003648 }
3649
Geoff Langf41d0ee2016-10-07 13:04:23 -04003650 if (length)
3651 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003652 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003653 }
3654
Jamie Madill0063c512014-08-25 15:47:53 -04003655 return true;
3656}
3657
He Yunchaoced53ae2016-11-29 15:00:51 +08003658bool ValidateGetnUniformfvEXT(Context *context,
3659 GLuint program,
3660 GLint location,
3661 GLsizei bufSize,
3662 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003663{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003664 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003665}
3666
He Yunchaoced53ae2016-11-29 15:00:51 +08003667bool ValidateGetnUniformivEXT(Context *context,
3668 GLuint program,
3669 GLint location,
3670 GLsizei bufSize,
3671 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003672{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003673 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3674}
3675
3676bool ValidateGetUniformfvRobustANGLE(Context *context,
3677 GLuint program,
3678 GLint location,
3679 GLsizei bufSize,
3680 GLsizei *length,
3681 GLfloat *params)
3682{
3683 if (!ValidateRobustEntryPoint(context, bufSize))
3684 {
3685 return false;
3686 }
3687
3688 // bufSize is validated in ValidateSizedGetUniform
3689 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3690}
3691
3692bool ValidateGetUniformivRobustANGLE(Context *context,
3693 GLuint program,
3694 GLint location,
3695 GLsizei bufSize,
3696 GLsizei *length,
3697 GLint *params)
3698{
3699 if (!ValidateRobustEntryPoint(context, bufSize))
3700 {
3701 return false;
3702 }
3703
3704 // bufSize is validated in ValidateSizedGetUniform
3705 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3706}
3707
3708bool ValidateGetUniformuivRobustANGLE(Context *context,
3709 GLuint program,
3710 GLint location,
3711 GLsizei bufSize,
3712 GLsizei *length,
3713 GLuint *params)
3714{
3715 if (!ValidateRobustEntryPoint(context, bufSize))
3716 {
3717 return false;
3718 }
3719
3720 if (context->getClientMajorVersion() < 3)
3721 {
3722 context->handleError(
3723 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3724 return false;
3725 }
3726
3727 // bufSize is validated in ValidateSizedGetUniform
3728 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003729}
3730
He Yunchaoced53ae2016-11-29 15:00:51 +08003731bool ValidateDiscardFramebufferBase(Context *context,
3732 GLenum target,
3733 GLsizei numAttachments,
3734 const GLenum *attachments,
3735 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003736{
3737 if (numAttachments < 0)
3738 {
Jamie Madill437fa652016-05-03 15:13:24 -04003739 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003740 return false;
3741 }
3742
3743 for (GLsizei i = 0; i < numAttachments; ++i)
3744 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003745 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003746 {
3747 if (defaultFramebuffer)
3748 {
Jamie Madill437fa652016-05-03 15:13:24 -04003749 context->handleError(Error(
3750 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003751 return false;
3752 }
3753
3754 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3755 {
Jamie Madill437fa652016-05-03 15:13:24 -04003756 context->handleError(Error(GL_INVALID_OPERATION,
3757 "Requested color attachment is greater than the maximum "
3758 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003759 return false;
3760 }
3761 }
3762 else
3763 {
3764 switch (attachments[i])
3765 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003766 case GL_DEPTH_ATTACHMENT:
3767 case GL_STENCIL_ATTACHMENT:
3768 case GL_DEPTH_STENCIL_ATTACHMENT:
3769 if (defaultFramebuffer)
3770 {
3771 context->handleError(
3772 Error(GL_INVALID_ENUM,
3773 "Invalid attachment when the default framebuffer is bound"));
3774 return false;
3775 }
3776 break;
3777 case GL_COLOR:
3778 case GL_DEPTH:
3779 case GL_STENCIL:
3780 if (!defaultFramebuffer)
3781 {
3782 context->handleError(
3783 Error(GL_INVALID_ENUM,
3784 "Invalid attachment when the default framebuffer is not bound"));
3785 return false;
3786 }
3787 break;
3788 default:
3789 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003790 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003791 }
3792 }
3793 }
3794
3795 return true;
3796}
3797
Austin Kinross6ee1e782015-05-29 17:05:37 -07003798bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3799{
3800 // Note that debug marker calls must not set error state
3801
3802 if (length < 0)
3803 {
3804 return false;
3805 }
3806
3807 if (marker == nullptr)
3808 {
3809 return false;
3810 }
3811
3812 return true;
3813}
3814
3815bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3816{
3817 // Note that debug marker calls must not set error state
3818
3819 if (length < 0)
3820 {
3821 return false;
3822 }
3823
3824 if (length > 0 && marker == nullptr)
3825 {
3826 return false;
3827 }
3828
3829 return true;
3830}
3831
Geoff Langdcab33b2015-07-21 13:03:16 -04003832bool ValidateEGLImageTargetTexture2DOES(Context *context,
3833 egl::Display *display,
3834 GLenum target,
3835 egl::Image *image)
3836{
Geoff Langa8406172015-07-21 16:53:39 -04003837 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3838 {
Jamie Madill437fa652016-05-03 15:13:24 -04003839 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003840 return false;
3841 }
3842
3843 switch (target)
3844 {
3845 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003846 if (!context->getExtensions().eglImage)
3847 {
3848 context->handleError(Error(
3849 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3850 }
3851 break;
3852
3853 case GL_TEXTURE_EXTERNAL_OES:
3854 if (!context->getExtensions().eglImageExternal)
3855 {
3856 context->handleError(Error(
3857 GL_INVALID_ENUM,
3858 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3859 }
Geoff Langa8406172015-07-21 16:53:39 -04003860 break;
3861
3862 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003863 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003864 return false;
3865 }
3866
3867 if (!display->isValidImage(image))
3868 {
Jamie Madill437fa652016-05-03 15:13:24 -04003869 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003870 return false;
3871 }
3872
3873 if (image->getSamples() > 0)
3874 {
Jamie Madill437fa652016-05-03 15:13:24 -04003875 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003876 "cannot create a 2D texture from a multisampled EGL image."));
3877 return false;
3878 }
3879
Jamie Madilla3944d42016-07-22 22:13:26 -04003880 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003881 if (!textureCaps.texturable)
3882 {
Jamie Madill437fa652016-05-03 15:13:24 -04003883 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003884 "EGL image internal format is not supported as a texture."));
3885 return false;
3886 }
3887
Geoff Langdcab33b2015-07-21 13:03:16 -04003888 return true;
3889}
3890
3891bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3892 egl::Display *display,
3893 GLenum target,
3894 egl::Image *image)
3895{
Geoff Langa8406172015-07-21 16:53:39 -04003896 if (!context->getExtensions().eglImage)
3897 {
Jamie Madill437fa652016-05-03 15:13:24 -04003898 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003899 return false;
3900 }
3901
3902 switch (target)
3903 {
3904 case GL_RENDERBUFFER:
3905 break;
3906
3907 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003908 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003909 return false;
3910 }
3911
3912 if (!display->isValidImage(image))
3913 {
Jamie Madill437fa652016-05-03 15:13:24 -04003914 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003915 return false;
3916 }
3917
Jamie Madilla3944d42016-07-22 22:13:26 -04003918 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003919 if (!textureCaps.renderable)
3920 {
Jamie Madill437fa652016-05-03 15:13:24 -04003921 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003922 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3923 return false;
3924 }
3925
Geoff Langdcab33b2015-07-21 13:03:16 -04003926 return true;
3927}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003928
3929bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3930{
Geoff Lang36167ab2015-12-07 10:27:14 -05003931 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003932 {
3933 // The default VAO should always exist
3934 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003935 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003936 return false;
3937 }
3938
3939 return true;
3940}
3941
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003942bool ValidateLinkProgram(Context *context, GLuint program)
3943{
3944 if (context->hasActiveTransformFeedback(program))
3945 {
3946 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003947 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003948 "Cannot link program while program is associated with an active "
3949 "transform feedback object."));
3950 return false;
3951 }
3952 return true;
3953}
3954
Geoff Langc5629752015-12-07 16:29:04 -05003955bool ValidateProgramBinaryBase(Context *context,
3956 GLuint program,
3957 GLenum binaryFormat,
3958 const void *binary,
3959 GLint length)
3960{
3961 Program *programObject = GetValidProgram(context, program);
3962 if (programObject == nullptr)
3963 {
3964 return false;
3965 }
3966
3967 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3968 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3969 programBinaryFormats.end())
3970 {
Jamie Madill437fa652016-05-03 15:13:24 -04003971 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003972 return false;
3973 }
3974
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003975 if (context->hasActiveTransformFeedback(program))
3976 {
3977 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003978 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003979 "Cannot change program binary while program is associated with "
3980 "an active transform feedback object."));
3981 return false;
3982 }
3983
Geoff Langc5629752015-12-07 16:29:04 -05003984 return true;
3985}
3986
3987bool ValidateGetProgramBinaryBase(Context *context,
3988 GLuint program,
3989 GLsizei bufSize,
3990 GLsizei *length,
3991 GLenum *binaryFormat,
3992 void *binary)
3993{
3994 Program *programObject = GetValidProgram(context, program);
3995 if (programObject == nullptr)
3996 {
3997 return false;
3998 }
3999
4000 if (!programObject->isLinked())
4001 {
Jamie Madill437fa652016-05-03 15:13:24 -04004002 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05004003 return false;
4004 }
4005
4006 return true;
4007}
Jamie Madillc29968b2016-01-20 11:17:23 -05004008
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004009bool ValidateUseProgram(Context *context, GLuint program)
4010{
4011 if (program != 0)
4012 {
4013 Program *programObject = context->getProgram(program);
4014 if (!programObject)
4015 {
4016 // ES 3.1.0 section 7.3 page 72
4017 if (context->getShader(program))
4018 {
Jamie Madill437fa652016-05-03 15:13:24 -04004019 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004020 Error(GL_INVALID_OPERATION,
4021 "Attempted to use a single shader instead of a shader program."));
4022 return false;
4023 }
4024 else
4025 {
Jamie Madill437fa652016-05-03 15:13:24 -04004026 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004027 return false;
4028 }
4029 }
4030 if (!programObject->isLinked())
4031 {
Jamie Madill437fa652016-05-03 15:13:24 -04004032 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004033 return false;
4034 }
4035 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004036 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004037 {
4038 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004039 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004040 Error(GL_INVALID_OPERATION,
4041 "Cannot change active program while transform feedback is unpaused."));
4042 return false;
4043 }
4044
4045 return true;
4046}
4047
Jamie Madillc29968b2016-01-20 11:17:23 -05004048bool ValidateCopyTexImage2D(ValidationContext *context,
4049 GLenum target,
4050 GLint level,
4051 GLenum internalformat,
4052 GLint x,
4053 GLint y,
4054 GLsizei width,
4055 GLsizei height,
4056 GLint border)
4057{
Martin Radev1be913c2016-07-11 17:59:16 +03004058 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004059 {
4060 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4061 0, x, y, width, height, border);
4062 }
4063
Martin Radev1be913c2016-07-11 17:59:16 +03004064 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004065 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4066 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004067}
Jamie Madillc29968b2016-01-20 11:17:23 -05004068
4069bool ValidateFramebufferRenderbuffer(Context *context,
4070 GLenum target,
4071 GLenum attachment,
4072 GLenum renderbuffertarget,
4073 GLuint renderbuffer)
4074{
4075 if (!ValidFramebufferTarget(target) ||
4076 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4077 {
Jamie Madill437fa652016-05-03 15:13:24 -04004078 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004079 return false;
4080 }
4081
4082 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4083 renderbuffertarget, renderbuffer);
4084}
4085
4086bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4087{
4088 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4089 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4090 {
Jamie Madill437fa652016-05-03 15:13:24 -04004091 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004092 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4093 return false;
4094 }
4095
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004096 ASSERT(context->getGLState().getDrawFramebuffer());
4097 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004098 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4099
4100 // This should come first before the check for the default frame buffer
4101 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4102 // rather than INVALID_OPERATION
4103 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4104 {
4105 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4106
4107 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004108 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4109 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004110 {
4111 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004112 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4113 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4114 // 3.1 is still a bit ambiguous about the error, but future specs are
4115 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004116 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004117 return false;
4118 }
4119 else if (bufs[colorAttachment] >= maxColorAttachment)
4120 {
Jamie Madill437fa652016-05-03 15:13:24 -04004121 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004122 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004123 return false;
4124 }
4125 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4126 frameBufferId != 0)
4127 {
4128 // INVALID_OPERATION-GL is bound to buffer and ith argument
4129 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004130 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004131 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4132 return false;
4133 }
4134 }
4135
4136 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4137 // and n is not 1 or bufs is bound to value other than BACK and NONE
4138 if (frameBufferId == 0)
4139 {
4140 if (n != 1)
4141 {
Jamie Madill437fa652016-05-03 15:13:24 -04004142 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004143 "n must be 1 when GL is bound to the default framebuffer"));
4144 return false;
4145 }
4146
4147 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4148 {
Jamie Madill437fa652016-05-03 15:13:24 -04004149 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004150 GL_INVALID_OPERATION,
4151 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4152 return false;
4153 }
4154 }
4155
4156 return true;
4157}
4158
4159bool ValidateCopyTexSubImage2D(Context *context,
4160 GLenum target,
4161 GLint level,
4162 GLint xoffset,
4163 GLint yoffset,
4164 GLint x,
4165 GLint y,
4166 GLsizei width,
4167 GLsizei height)
4168{
Martin Radev1be913c2016-07-11 17:59:16 +03004169 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004170 {
4171 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4172 yoffset, x, y, width, height, 0);
4173 }
4174
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004175 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4176 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004177}
4178
Geoff Lang496c02d2016-10-20 11:38:11 -07004179bool ValidateGetBufferPointervBase(Context *context,
4180 GLenum target,
4181 GLenum pname,
4182 GLsizei *length,
4183 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004184{
Geoff Lang496c02d2016-10-20 11:38:11 -07004185 if (length)
4186 {
4187 *length = 0;
4188 }
4189
4190 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4191 {
4192 context->handleError(
4193 Error(GL_INVALID_OPERATION,
4194 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
4195 return false;
4196 }
4197
Olli Etuaho4f667482016-03-30 15:56:35 +03004198 if (!ValidBufferTarget(context, target))
4199 {
Jamie Madill437fa652016-05-03 15:13:24 -04004200 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004201 return false;
4202 }
4203
Geoff Lang496c02d2016-10-20 11:38:11 -07004204 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004205 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004206 case GL_BUFFER_MAP_POINTER:
4207 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004208
Geoff Lang496c02d2016-10-20 11:38:11 -07004209 default:
4210 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4211 return false;
4212 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004213
4214 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4215 // target bound to zero generate an INVALID_OPERATION error."
4216 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004217 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004218 {
Jamie Madill437fa652016-05-03 15:13:24 -04004219 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004220 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4221 return false;
4222 }
4223
Geoff Lang496c02d2016-10-20 11:38:11 -07004224 if (length)
4225 {
4226 *length = 1;
4227 }
4228
Olli Etuaho4f667482016-03-30 15:56:35 +03004229 return true;
4230}
4231
4232bool ValidateUnmapBufferBase(Context *context, GLenum target)
4233{
4234 if (!ValidBufferTarget(context, target))
4235 {
Jamie Madill437fa652016-05-03 15:13:24 -04004236 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004237 return false;
4238 }
4239
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004240 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004241
4242 if (buffer == nullptr || !buffer->isMapped())
4243 {
Jamie Madill437fa652016-05-03 15:13:24 -04004244 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004245 return false;
4246 }
4247
4248 return true;
4249}
4250
4251bool ValidateMapBufferRangeBase(Context *context,
4252 GLenum target,
4253 GLintptr offset,
4254 GLsizeiptr length,
4255 GLbitfield access)
4256{
4257 if (!ValidBufferTarget(context, target))
4258 {
Jamie Madill437fa652016-05-03 15:13:24 -04004259 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004260 return false;
4261 }
4262
4263 if (offset < 0 || length < 0)
4264 {
Jamie Madill437fa652016-05-03 15:13:24 -04004265 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004266 return false;
4267 }
4268
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004269 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004270
4271 if (!buffer)
4272 {
Jamie Madill437fa652016-05-03 15:13:24 -04004273 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004274 return false;
4275 }
4276
4277 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004278 CheckedNumeric<size_t> checkedOffset(offset);
4279 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004280
Jamie Madille2e406c2016-06-02 13:04:10 -04004281 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004282 {
Jamie Madill437fa652016-05-03 15:13:24 -04004283 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004284 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4285 return false;
4286 }
4287
4288 // Check for invalid bits in the mask
4289 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4290 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4291 GL_MAP_UNSYNCHRONIZED_BIT;
4292
4293 if (access & ~(allAccessBits))
4294 {
Jamie Madill437fa652016-05-03 15:13:24 -04004295 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004296 return false;
4297 }
4298
4299 if (length == 0)
4300 {
Jamie Madill437fa652016-05-03 15:13:24 -04004301 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004302 return false;
4303 }
4304
4305 if (buffer->isMapped())
4306 {
Jamie Madill437fa652016-05-03 15:13:24 -04004307 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004308 return false;
4309 }
4310
4311 // Check for invalid bit combinations
4312 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4313 {
Jamie Madill437fa652016-05-03 15:13:24 -04004314 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004315 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4316 return false;
4317 }
4318
4319 GLbitfield writeOnlyBits =
4320 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4321
4322 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4323 {
Jamie Madill437fa652016-05-03 15:13:24 -04004324 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004325 "Invalid access bits when mapping buffer for reading: 0x%X.",
4326 access));
4327 return false;
4328 }
4329
4330 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4331 {
Jamie Madill437fa652016-05-03 15:13:24 -04004332 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004333 GL_INVALID_OPERATION,
4334 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4335 return false;
4336 }
4337 return true;
4338}
4339
4340bool ValidateFlushMappedBufferRangeBase(Context *context,
4341 GLenum target,
4342 GLintptr offset,
4343 GLsizeiptr length)
4344{
4345 if (offset < 0 || length < 0)
4346 {
Jamie Madill437fa652016-05-03 15:13:24 -04004347 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004348 return false;
4349 }
4350
4351 if (!ValidBufferTarget(context, target))
4352 {
Jamie Madill437fa652016-05-03 15:13:24 -04004353 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004354 return false;
4355 }
4356
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004357 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004358
4359 if (buffer == nullptr)
4360 {
Jamie Madill437fa652016-05-03 15:13:24 -04004361 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004362 return false;
4363 }
4364
4365 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4366 {
Jamie Madill437fa652016-05-03 15:13:24 -04004367 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004368 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4369 return false;
4370 }
4371
4372 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004373 CheckedNumeric<size_t> checkedOffset(offset);
4374 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004375
Jamie Madille2e406c2016-06-02 13:04:10 -04004376 if (!checkedSize.IsValid() ||
4377 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004378 {
Jamie Madill437fa652016-05-03 15:13:24 -04004379 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004380 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4381 return false;
4382 }
4383
4384 return true;
4385}
4386
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004387bool ValidateGenerateMipmap(Context *context, GLenum target)
4388{
4389 if (!ValidTextureTarget(context, target))
4390 {
4391 context->handleError(Error(GL_INVALID_ENUM));
4392 return false;
4393 }
4394
4395 Texture *texture = context->getTargetTexture(target);
4396
4397 if (texture == nullptr)
4398 {
4399 context->handleError(Error(GL_INVALID_OPERATION));
4400 return false;
4401 }
4402
4403 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4404
4405 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4406 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4407 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4408 {
4409 context->handleError(Error(GL_INVALID_OPERATION));
4410 return false;
4411 }
4412
Jamie Madilla3944d42016-07-22 22:13:26 -04004413 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4414 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4415 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004416
4417 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4418 // unsized formats or that are color renderable and filterable. Since we do not track if
4419 // the texture was created with sized or unsized format (only sized formats are stored),
4420 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4421 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4422 // textures since they're the only texture format that can be created with unsized formats
4423 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4424 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004425 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4426 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004427 {
4428 context->handleError(Error(GL_INVALID_OPERATION));
4429 return false;
4430 }
4431
4432 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004433 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004434 {
4435 context->handleError(Error(GL_INVALID_OPERATION));
4436 return false;
4437 }
4438
4439 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004440 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004441 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4442 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4443 {
Geoff Lang55482a12016-11-21 16:54:01 -05004444 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004445 context->handleError(Error(GL_INVALID_OPERATION));
4446 return false;
4447 }
4448
4449 // Cube completeness check
4450 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4451 {
4452 context->handleError(Error(GL_INVALID_OPERATION));
4453 return false;
4454 }
4455
4456 return true;
4457}
4458
Olli Etuaho41997e72016-03-10 13:38:39 +02004459bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4460{
4461 return ValidateGenOrDelete(context, n);
4462}
4463
4464bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4465{
4466 return ValidateGenOrDelete(context, n);
4467}
4468
4469bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4470{
4471 return ValidateGenOrDelete(context, n);
4472}
4473
4474bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4475{
4476 return ValidateGenOrDelete(context, n);
4477}
4478
4479bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4480{
4481 return ValidateGenOrDelete(context, n);
4482}
4483
4484bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4485{
4486 return ValidateGenOrDelete(context, n);
4487}
4488
4489bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4490{
4491 return ValidateGenOrDelete(context, n);
4492}
4493
4494bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4495{
4496 return ValidateGenOrDelete(context, n);
4497}
4498
4499bool ValidateGenOrDelete(Context *context, GLint n)
4500{
4501 if (n < 0)
4502 {
Jamie Madill437fa652016-05-03 15:13:24 -04004503 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004504 return false;
4505 }
4506 return true;
4507}
4508
Geoff Langf41a7152016-09-19 15:11:17 -04004509bool ValidateEnable(Context *context, GLenum cap)
4510{
4511 if (!ValidCap(context, cap, false))
4512 {
4513 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4514 return false;
4515 }
4516
4517 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4518 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4519 {
4520 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4521 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4522
4523 // We also output an error message to the debugger window if tracing is active, so that
4524 // developers can see the error message.
4525 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004526 return false;
4527 }
4528
4529 return true;
4530}
4531
4532bool ValidateDisable(Context *context, GLenum cap)
4533{
4534 if (!ValidCap(context, cap, false))
4535 {
4536 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4537 return false;
4538 }
4539
4540 return true;
4541}
4542
4543bool ValidateIsEnabled(Context *context, GLenum cap)
4544{
4545 if (!ValidCap(context, cap, true))
4546 {
4547 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4548 return false;
4549 }
4550
4551 return true;
4552}
4553
Geoff Langff5b2d52016-09-07 11:32:23 -04004554bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4555{
4556 if (!context->getExtensions().robustClientMemory)
4557 {
4558 context->handleError(
4559 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4560 return false;
4561 }
4562
4563 if (bufSize < 0)
4564 {
4565 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4566 return false;
4567 }
4568
4569 return true;
4570}
4571
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004572bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4573{
4574 if (bufSize < numParams)
4575 {
4576 context->handleError(Error(GL_INVALID_OPERATION,
4577 "%u parameters are required but %i were provided.", numParams,
4578 bufSize));
4579 return false;
4580 }
4581
4582 return true;
4583}
4584
Geoff Langff5b2d52016-09-07 11:32:23 -04004585bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4586 GLenum target,
4587 GLenum attachment,
4588 GLenum pname,
4589 GLsizei *numParams)
4590{
4591 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4592 *numParams = 1;
4593
4594 if (!ValidFramebufferTarget(target))
4595 {
4596 context->handleError(Error(GL_INVALID_ENUM));
4597 return false;
4598 }
4599
4600 int clientVersion = context->getClientMajorVersion();
4601
4602 switch (pname)
4603 {
4604 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4605 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4606 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4607 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4608 break;
4609
4610 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4611 if (clientVersion < 3 && !context->getExtensions().sRGB)
4612 {
4613 context->handleError(Error(GL_INVALID_ENUM));
4614 return false;
4615 }
4616 break;
4617
4618 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4619 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4620 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4621 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4622 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4623 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4624 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4625 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4626 if (clientVersion < 3)
4627 {
4628 context->handleError(Error(GL_INVALID_ENUM));
4629 return false;
4630 }
4631 break;
4632
4633 default:
4634 context->handleError(Error(GL_INVALID_ENUM));
4635 return false;
4636 }
4637
4638 // Determine if the attachment is a valid enum
4639 switch (attachment)
4640 {
4641 case GL_BACK:
4642 case GL_FRONT:
4643 case GL_DEPTH:
4644 case GL_STENCIL:
4645 case GL_DEPTH_STENCIL_ATTACHMENT:
4646 if (clientVersion < 3)
4647 {
4648 context->handleError(Error(GL_INVALID_ENUM));
4649 return false;
4650 }
4651 break;
4652
4653 case GL_DEPTH_ATTACHMENT:
4654 case GL_STENCIL_ATTACHMENT:
4655 break;
4656
4657 default:
4658 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4659 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4660 {
4661 context->handleError(Error(GL_INVALID_ENUM));
4662 return false;
4663 }
4664 break;
4665 }
4666
4667 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4668 ASSERT(framebuffer);
4669
4670 if (framebuffer->id() == 0)
4671 {
4672 if (clientVersion < 3)
4673 {
4674 context->handleError(Error(GL_INVALID_OPERATION));
4675 return false;
4676 }
4677
4678 switch (attachment)
4679 {
4680 case GL_BACK:
4681 case GL_DEPTH:
4682 case GL_STENCIL:
4683 break;
4684
4685 default:
4686 context->handleError(Error(GL_INVALID_OPERATION));
4687 return false;
4688 }
4689 }
4690 else
4691 {
4692 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4693 {
4694 // Valid attachment query
4695 }
4696 else
4697 {
4698 switch (attachment)
4699 {
4700 case GL_DEPTH_ATTACHMENT:
4701 case GL_STENCIL_ATTACHMENT:
4702 break;
4703
4704 case GL_DEPTH_STENCIL_ATTACHMENT:
4705 if (!framebuffer->hasValidDepthStencil())
4706 {
4707 context->handleError(Error(GL_INVALID_OPERATION));
4708 return false;
4709 }
4710 break;
4711
4712 default:
4713 context->handleError(Error(GL_INVALID_OPERATION));
4714 return false;
4715 }
4716 }
4717 }
4718
4719 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4720 if (attachmentObject)
4721 {
4722 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4723 attachmentObject->type() == GL_TEXTURE ||
4724 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4725
4726 switch (pname)
4727 {
4728 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4729 if (attachmentObject->type() != GL_RENDERBUFFER &&
4730 attachmentObject->type() != GL_TEXTURE)
4731 {
4732 context->handleError(Error(GL_INVALID_ENUM));
4733 return false;
4734 }
4735 break;
4736
4737 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4738 if (attachmentObject->type() != GL_TEXTURE)
4739 {
4740 context->handleError(Error(GL_INVALID_ENUM));
4741 return false;
4742 }
4743 break;
4744
4745 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4746 if (attachmentObject->type() != GL_TEXTURE)
4747 {
4748 context->handleError(Error(GL_INVALID_ENUM));
4749 return false;
4750 }
4751 break;
4752
4753 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4754 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4755 {
4756 context->handleError(Error(GL_INVALID_OPERATION));
4757 return false;
4758 }
4759 break;
4760
4761 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4762 if (attachmentObject->type() != GL_TEXTURE)
4763 {
4764 context->handleError(Error(GL_INVALID_ENUM));
4765 return false;
4766 }
4767 break;
4768
4769 default:
4770 break;
4771 }
4772 }
4773 else
4774 {
4775 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4776 // is NONE, then querying any other pname will generate INVALID_ENUM.
4777
4778 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4779 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4780 // INVALID_OPERATION for all other pnames
4781
4782 switch (pname)
4783 {
4784 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4785 break;
4786
4787 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4788 if (clientVersion < 3)
4789 {
4790 context->handleError(Error(GL_INVALID_ENUM));
4791 return false;
4792 }
4793 break;
4794
4795 default:
4796 if (clientVersion < 3)
4797 {
4798 context->handleError(Error(GL_INVALID_ENUM));
4799 return false;
4800 }
4801 else
4802 {
4803 context->handleError(Error(GL_INVALID_OPERATION));
4804 return false;
4805 }
4806 }
4807 }
4808
4809 return true;
4810}
4811
4812bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4813 GLenum target,
4814 GLenum attachment,
4815 GLenum pname,
4816 GLsizei bufSize,
4817 GLsizei *numParams)
4818{
4819 if (!ValidateRobustEntryPoint(context, bufSize))
4820 {
4821 return false;
4822 }
4823
4824 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4825 {
4826 return false;
4827 }
4828
4829 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4830 {
4831 return false;
4832 }
4833
4834 return true;
4835}
4836
4837bool ValidateGetBufferParameteriv(ValidationContext *context,
4838 GLenum target,
4839 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004840 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004841{
Geoff Langebebe1c2016-10-14 12:01:31 -04004842 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004843}
4844
4845bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4846 GLenum target,
4847 GLenum pname,
4848 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004849 GLsizei *length,
4850 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004851{
4852 if (!ValidateRobustEntryPoint(context, bufSize))
4853 {
4854 return false;
4855 }
4856
Geoff Langebebe1c2016-10-14 12:01:31 -04004857 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004858 {
4859 return false;
4860 }
4861
Geoff Langebebe1c2016-10-14 12:01:31 -04004862 if (!ValidateRobustBufferSize(context, bufSize, *length))
4863 {
4864 return false;
4865 }
4866
4867 return true;
4868}
4869
4870bool ValidateGetBufferParameteri64v(ValidationContext *context,
4871 GLenum target,
4872 GLenum pname,
4873 GLint64 *params)
4874{
4875 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4876}
4877
4878bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4879 GLenum target,
4880 GLenum pname,
4881 GLsizei bufSize,
4882 GLsizei *length,
4883 GLint64 *params)
4884{
4885 if (!ValidateRobustEntryPoint(context, bufSize))
4886 {
4887 return false;
4888 }
4889
4890 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4891 {
4892 return false;
4893 }
4894
4895 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004896 {
4897 return false;
4898 }
4899
4900 return true;
4901}
4902
4903bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4904{
4905 // Currently, all GetProgramiv queries return 1 parameter
4906 *numParams = 1;
4907
4908 Program *programObject = GetValidProgram(context, program);
4909 if (!programObject)
4910 {
4911 return false;
4912 }
4913
4914 switch (pname)
4915 {
4916 case GL_DELETE_STATUS:
4917 case GL_LINK_STATUS:
4918 case GL_VALIDATE_STATUS:
4919 case GL_INFO_LOG_LENGTH:
4920 case GL_ATTACHED_SHADERS:
4921 case GL_ACTIVE_ATTRIBUTES:
4922 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4923 case GL_ACTIVE_UNIFORMS:
4924 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4925 break;
4926
4927 case GL_PROGRAM_BINARY_LENGTH:
4928 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4929 {
4930 context->handleError(Error(GL_INVALID_ENUM,
4931 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4932 "GL_OES_get_program_binary or ES 3.0."));
4933 return false;
4934 }
4935 break;
4936
4937 case GL_ACTIVE_UNIFORM_BLOCKS:
4938 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4939 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4940 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4941 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4942 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4943 if (context->getClientMajorVersion() < 3)
4944 {
4945 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4946 return false;
4947 }
4948 break;
4949
4950 default:
4951 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4952 return false;
4953 }
4954
4955 return true;
4956}
4957
4958bool ValidateGetProgramivRobustANGLE(Context *context,
4959 GLuint program,
4960 GLenum pname,
4961 GLsizei bufSize,
4962 GLsizei *numParams)
4963{
4964 if (!ValidateRobustEntryPoint(context, bufSize))
4965 {
4966 return false;
4967 }
4968
4969 if (!ValidateGetProgramiv(context, program, pname, numParams))
4970 {
4971 return false;
4972 }
4973
4974 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4975 {
4976 return false;
4977 }
4978
4979 return true;
4980}
4981
Geoff Lang740d9022016-10-07 11:20:52 -04004982bool ValidateGetRenderbufferParameteriv(Context *context,
4983 GLenum target,
4984 GLenum pname,
4985 GLint *params)
4986{
4987 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4988}
4989
4990bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4991 GLenum target,
4992 GLenum pname,
4993 GLsizei bufSize,
4994 GLsizei *length,
4995 GLint *params)
4996{
4997 if (!ValidateRobustEntryPoint(context, bufSize))
4998 {
4999 return false;
5000 }
5001
5002 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5003 {
5004 return false;
5005 }
5006
5007 if (!ValidateRobustBufferSize(context, bufSize, *length))
5008 {
5009 return false;
5010 }
5011
5012 return true;
5013}
5014
Geoff Langd7d0ed32016-10-07 11:33:51 -04005015bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5016{
5017 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5018}
5019
5020bool ValidateGetShaderivRobustANGLE(Context *context,
5021 GLuint shader,
5022 GLenum pname,
5023 GLsizei bufSize,
5024 GLsizei *length,
5025 GLint *params)
5026{
5027 if (!ValidateRobustEntryPoint(context, bufSize))
5028 {
5029 return false;
5030 }
5031
5032 if (!ValidateGetShaderivBase(context, shader, pname, length))
5033 {
5034 return false;
5035 }
5036
5037 if (!ValidateRobustBufferSize(context, bufSize, *length))
5038 {
5039 return false;
5040 }
5041
5042 return true;
5043}
5044
Geoff Langc1984ed2016-10-07 12:41:00 -04005045bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5046{
5047 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5048}
5049
5050bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5051 GLenum target,
5052 GLenum pname,
5053 GLsizei bufSize,
5054 GLsizei *length,
5055 GLfloat *params)
5056{
5057 if (!ValidateRobustEntryPoint(context, bufSize))
5058 {
5059 return false;
5060 }
5061
5062 if (!ValidateGetTexParameterBase(context, target, pname, length))
5063 {
5064 return false;
5065 }
5066
5067 if (!ValidateRobustBufferSize(context, bufSize, *length))
5068 {
5069 return false;
5070 }
5071
5072 return true;
5073}
5074
5075bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5076{
5077 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5078}
5079
5080bool ValidateGetTexParameterivRobustANGLE(Context *context,
5081 GLenum target,
5082 GLenum pname,
5083 GLsizei bufSize,
5084 GLsizei *length,
5085 GLint *params)
5086{
5087 if (!ValidateRobustEntryPoint(context, bufSize))
5088 {
5089 return false;
5090 }
5091
5092 if (!ValidateGetTexParameterBase(context, target, pname, length))
5093 {
5094 return false;
5095 }
5096
5097 if (!ValidateRobustBufferSize(context, bufSize, *length))
5098 {
5099 return false;
5100 }
5101
5102 return true;
5103}
5104
5105bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5106{
5107 return ValidateTexParameterBase(context, target, pname, -1, &param);
5108}
5109
5110bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5111{
5112 return ValidateTexParameterBase(context, target, pname, -1, params);
5113}
5114
5115bool ValidateTexParameterfvRobustANGLE(Context *context,
5116 GLenum target,
5117 GLenum pname,
5118 GLsizei bufSize,
5119 const GLfloat *params)
5120{
5121 if (!ValidateRobustEntryPoint(context, bufSize))
5122 {
5123 return false;
5124 }
5125
5126 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5127}
5128
5129bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5130{
5131 return ValidateTexParameterBase(context, target, pname, -1, &param);
5132}
5133
5134bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5135{
5136 return ValidateTexParameterBase(context, target, pname, -1, params);
5137}
5138
5139bool ValidateTexParameterivRobustANGLE(Context *context,
5140 GLenum target,
5141 GLenum pname,
5142 GLsizei bufSize,
5143 const GLint *params)
5144{
5145 if (!ValidateRobustEntryPoint(context, bufSize))
5146 {
5147 return false;
5148 }
5149
5150 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5151}
5152
5153bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5154{
5155 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5156}
5157
5158bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5159 GLuint sampler,
5160 GLenum pname,
5161 GLuint bufSize,
5162 GLsizei *length,
5163 GLfloat *params)
5164{
5165 if (!ValidateRobustEntryPoint(context, bufSize))
5166 {
5167 return false;
5168 }
5169
5170 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5171 {
5172 return false;
5173 }
5174
5175 if (!ValidateRobustBufferSize(context, bufSize, *length))
5176 {
5177 return false;
5178 }
5179
5180 return true;
5181}
5182
5183bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5184{
5185 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5186}
5187
5188bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5189 GLuint sampler,
5190 GLenum pname,
5191 GLuint bufSize,
5192 GLsizei *length,
5193 GLint *params)
5194{
5195 if (!ValidateRobustEntryPoint(context, bufSize))
5196 {
5197 return false;
5198 }
5199
5200 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5201 {
5202 return false;
5203 }
5204
5205 if (!ValidateRobustBufferSize(context, bufSize, *length))
5206 {
5207 return false;
5208 }
5209
5210 return true;
5211}
5212
5213bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5214{
5215 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5216}
5217
5218bool ValidateSamplerParameterfv(Context *context,
5219 GLuint sampler,
5220 GLenum pname,
5221 const GLfloat *params)
5222{
5223 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5224}
5225
5226bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5227 GLuint sampler,
5228 GLenum pname,
5229 GLsizei bufSize,
5230 const GLfloat *params)
5231{
5232 if (!ValidateRobustEntryPoint(context, bufSize))
5233 {
5234 return false;
5235 }
5236
5237 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5238}
5239
5240bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5241{
5242 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5243}
5244
5245bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5246{
5247 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5248}
5249
5250bool ValidateSamplerParameterivRobustANGLE(Context *context,
5251 GLuint sampler,
5252 GLenum pname,
5253 GLsizei bufSize,
5254 const GLint *params)
5255{
5256 if (!ValidateRobustEntryPoint(context, bufSize))
5257 {
5258 return false;
5259 }
5260
5261 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5262}
5263
Geoff Lang0b031062016-10-13 14:30:04 -04005264bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5265{
5266 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5267}
5268
5269bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5270 GLuint index,
5271 GLenum pname,
5272 GLsizei bufSize,
5273 GLsizei *length,
5274 GLfloat *params)
5275{
5276 if (!ValidateRobustEntryPoint(context, bufSize))
5277 {
5278 return false;
5279 }
5280
5281 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5282 {
5283 return false;
5284 }
5285
5286 if (!ValidateRobustBufferSize(context, bufSize, *length))
5287 {
5288 return false;
5289 }
5290
5291 return true;
5292}
5293
5294bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5295{
5296 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5297}
5298
5299bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5300 GLuint index,
5301 GLenum pname,
5302 GLsizei bufSize,
5303 GLsizei *length,
5304 GLint *params)
5305{
5306 if (!ValidateRobustEntryPoint(context, bufSize))
5307 {
5308 return false;
5309 }
5310
5311 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5312 {
5313 return false;
5314 }
5315
5316 if (!ValidateRobustBufferSize(context, bufSize, *length))
5317 {
5318 return false;
5319 }
5320
5321 return true;
5322}
5323
5324bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5325{
5326 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5327}
5328
5329bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5330 GLuint index,
5331 GLenum pname,
5332 GLsizei bufSize,
5333 GLsizei *length,
5334 void **pointer)
5335{
5336 if (!ValidateRobustEntryPoint(context, bufSize))
5337 {
5338 return false;
5339 }
5340
5341 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5342 {
5343 return false;
5344 }
5345
5346 if (!ValidateRobustBufferSize(context, bufSize, *length))
5347 {
5348 return false;
5349 }
5350
5351 return true;
5352}
5353
5354bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5355{
5356 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5357}
5358
5359bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5360 GLuint index,
5361 GLenum pname,
5362 GLsizei bufSize,
5363 GLsizei *length,
5364 GLint *params)
5365{
5366 if (!ValidateRobustEntryPoint(context, bufSize))
5367 {
5368 return false;
5369 }
5370
5371 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5372 {
5373 return false;
5374 }
5375
5376 if (!ValidateRobustBufferSize(context, bufSize, *length))
5377 {
5378 return false;
5379 }
5380
5381 return true;
5382}
5383
5384bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5385{
5386 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5387}
5388
5389bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5390 GLuint index,
5391 GLenum pname,
5392 GLsizei bufSize,
5393 GLsizei *length,
5394 GLuint *params)
5395{
5396 if (!ValidateRobustEntryPoint(context, bufSize))
5397 {
5398 return false;
5399 }
5400
5401 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5402 {
5403 return false;
5404 }
5405
5406 if (!ValidateRobustBufferSize(context, bufSize, *length))
5407 {
5408 return false;
5409 }
5410
5411 return true;
5412}
5413
Geoff Lang6899b872016-10-14 11:30:13 -04005414bool ValidateGetActiveUniformBlockiv(Context *context,
5415 GLuint program,
5416 GLuint uniformBlockIndex,
5417 GLenum pname,
5418 GLint *params)
5419{
5420 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5421}
5422
5423bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5424 GLuint program,
5425 GLuint uniformBlockIndex,
5426 GLenum pname,
5427 GLsizei bufSize,
5428 GLsizei *length,
5429 GLint *params)
5430{
5431 if (!ValidateRobustEntryPoint(context, bufSize))
5432 {
5433 return false;
5434 }
5435
5436 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5437 {
5438 return false;
5439 }
5440
5441 if (!ValidateRobustBufferSize(context, bufSize, *length))
5442 {
5443 return false;
5444 }
5445
5446 return true;
5447}
5448
Geoff Lang0a9661f2016-10-20 10:59:20 -07005449bool ValidateGetInternalFormativ(Context *context,
5450 GLenum target,
5451 GLenum internalformat,
5452 GLenum pname,
5453 GLsizei bufSize,
5454 GLint *params)
5455{
5456 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5457 nullptr);
5458}
5459
5460bool ValidateGetInternalFormativRobustANGLE(Context *context,
5461 GLenum target,
5462 GLenum internalformat,
5463 GLenum pname,
5464 GLsizei bufSize,
5465 GLsizei *length,
5466 GLint *params)
5467{
5468 if (!ValidateRobustEntryPoint(context, bufSize))
5469 {
5470 return false;
5471 }
5472
5473 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5474 {
5475 return false;
5476 }
5477
5478 if (!ValidateRobustBufferSize(context, bufSize, *length))
5479 {
5480 return false;
5481 }
5482
5483 return true;
5484}
5485
Jamie Madillc29968b2016-01-20 11:17:23 -05005486} // namespace gl