blob: d2d3a2baea46638cedd3a7f0838ff98b7876d8e7 [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
Jamie Madilla7d12dc2016-12-13 15:08:19 -05004006 if (context->getCaps().programBinaryFormats.empty())
4007 {
4008 context->handleError(Error(GL_INVALID_OPERATION, "No program binary formats supported."));
4009 return false;
4010 }
4011
Geoff Langc5629752015-12-07 16:29:04 -05004012 return true;
4013}
Jamie Madillc29968b2016-01-20 11:17:23 -05004014
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004015bool ValidateUseProgram(Context *context, GLuint program)
4016{
4017 if (program != 0)
4018 {
4019 Program *programObject = context->getProgram(program);
4020 if (!programObject)
4021 {
4022 // ES 3.1.0 section 7.3 page 72
4023 if (context->getShader(program))
4024 {
Jamie Madill437fa652016-05-03 15:13:24 -04004025 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004026 Error(GL_INVALID_OPERATION,
4027 "Attempted to use a single shader instead of a shader program."));
4028 return false;
4029 }
4030 else
4031 {
Jamie Madill437fa652016-05-03 15:13:24 -04004032 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004033 return false;
4034 }
4035 }
4036 if (!programObject->isLinked())
4037 {
Jamie Madill437fa652016-05-03 15:13:24 -04004038 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004039 return false;
4040 }
4041 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004042 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004043 {
4044 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004045 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004046 Error(GL_INVALID_OPERATION,
4047 "Cannot change active program while transform feedback is unpaused."));
4048 return false;
4049 }
4050
4051 return true;
4052}
4053
Jamie Madillc29968b2016-01-20 11:17:23 -05004054bool ValidateCopyTexImage2D(ValidationContext *context,
4055 GLenum target,
4056 GLint level,
4057 GLenum internalformat,
4058 GLint x,
4059 GLint y,
4060 GLsizei width,
4061 GLsizei height,
4062 GLint border)
4063{
Martin Radev1be913c2016-07-11 17:59:16 +03004064 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004065 {
4066 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4067 0, x, y, width, height, border);
4068 }
4069
Martin Radev1be913c2016-07-11 17:59:16 +03004070 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004071 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4072 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004073}
Jamie Madillc29968b2016-01-20 11:17:23 -05004074
4075bool ValidateFramebufferRenderbuffer(Context *context,
4076 GLenum target,
4077 GLenum attachment,
4078 GLenum renderbuffertarget,
4079 GLuint renderbuffer)
4080{
4081 if (!ValidFramebufferTarget(target) ||
4082 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4083 {
Jamie Madill437fa652016-05-03 15:13:24 -04004084 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004085 return false;
4086 }
4087
4088 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4089 renderbuffertarget, renderbuffer);
4090}
4091
4092bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4093{
4094 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4095 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4096 {
Jamie Madill437fa652016-05-03 15:13:24 -04004097 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004098 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4099 return false;
4100 }
4101
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004102 ASSERT(context->getGLState().getDrawFramebuffer());
4103 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004104 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4105
4106 // This should come first before the check for the default frame buffer
4107 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4108 // rather than INVALID_OPERATION
4109 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4110 {
4111 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4112
4113 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004114 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4115 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004116 {
4117 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004118 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4119 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4120 // 3.1 is still a bit ambiguous about the error, but future specs are
4121 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004122 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004123 return false;
4124 }
4125 else if (bufs[colorAttachment] >= maxColorAttachment)
4126 {
Jamie Madill437fa652016-05-03 15:13:24 -04004127 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004128 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004129 return false;
4130 }
4131 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4132 frameBufferId != 0)
4133 {
4134 // INVALID_OPERATION-GL is bound to buffer and ith argument
4135 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004136 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004137 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4138 return false;
4139 }
4140 }
4141
4142 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4143 // and n is not 1 or bufs is bound to value other than BACK and NONE
4144 if (frameBufferId == 0)
4145 {
4146 if (n != 1)
4147 {
Jamie Madill437fa652016-05-03 15:13:24 -04004148 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004149 "n must be 1 when GL is bound to the default framebuffer"));
4150 return false;
4151 }
4152
4153 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4154 {
Jamie Madill437fa652016-05-03 15:13:24 -04004155 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004156 GL_INVALID_OPERATION,
4157 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4158 return false;
4159 }
4160 }
4161
4162 return true;
4163}
4164
4165bool ValidateCopyTexSubImage2D(Context *context,
4166 GLenum target,
4167 GLint level,
4168 GLint xoffset,
4169 GLint yoffset,
4170 GLint x,
4171 GLint y,
4172 GLsizei width,
4173 GLsizei height)
4174{
Martin Radev1be913c2016-07-11 17:59:16 +03004175 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004176 {
4177 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4178 yoffset, x, y, width, height, 0);
4179 }
4180
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004181 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4182 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004183}
4184
Geoff Lang496c02d2016-10-20 11:38:11 -07004185bool ValidateGetBufferPointervBase(Context *context,
4186 GLenum target,
4187 GLenum pname,
4188 GLsizei *length,
4189 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004190{
Geoff Lang496c02d2016-10-20 11:38:11 -07004191 if (length)
4192 {
4193 *length = 0;
4194 }
4195
4196 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4197 {
4198 context->handleError(
4199 Error(GL_INVALID_OPERATION,
4200 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
4201 return false;
4202 }
4203
Olli Etuaho4f667482016-03-30 15:56:35 +03004204 if (!ValidBufferTarget(context, target))
4205 {
Jamie Madill437fa652016-05-03 15:13:24 -04004206 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004207 return false;
4208 }
4209
Geoff Lang496c02d2016-10-20 11:38:11 -07004210 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004211 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004212 case GL_BUFFER_MAP_POINTER:
4213 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004214
Geoff Lang496c02d2016-10-20 11:38:11 -07004215 default:
4216 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4217 return false;
4218 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004219
4220 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4221 // target bound to zero generate an INVALID_OPERATION error."
4222 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004223 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004224 {
Jamie Madill437fa652016-05-03 15:13:24 -04004225 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004226 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4227 return false;
4228 }
4229
Geoff Lang496c02d2016-10-20 11:38:11 -07004230 if (length)
4231 {
4232 *length = 1;
4233 }
4234
Olli Etuaho4f667482016-03-30 15:56:35 +03004235 return true;
4236}
4237
4238bool ValidateUnmapBufferBase(Context *context, GLenum target)
4239{
4240 if (!ValidBufferTarget(context, target))
4241 {
Jamie Madill437fa652016-05-03 15:13:24 -04004242 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004243 return false;
4244 }
4245
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004246 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004247
4248 if (buffer == nullptr || !buffer->isMapped())
4249 {
Jamie Madill437fa652016-05-03 15:13:24 -04004250 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004251 return false;
4252 }
4253
4254 return true;
4255}
4256
4257bool ValidateMapBufferRangeBase(Context *context,
4258 GLenum target,
4259 GLintptr offset,
4260 GLsizeiptr length,
4261 GLbitfield access)
4262{
4263 if (!ValidBufferTarget(context, target))
4264 {
Jamie Madill437fa652016-05-03 15:13:24 -04004265 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004266 return false;
4267 }
4268
4269 if (offset < 0 || length < 0)
4270 {
Jamie Madill437fa652016-05-03 15:13:24 -04004271 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004272 return false;
4273 }
4274
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004275 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004276
4277 if (!buffer)
4278 {
Jamie Madill437fa652016-05-03 15:13:24 -04004279 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004280 return false;
4281 }
4282
4283 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004284 CheckedNumeric<size_t> checkedOffset(offset);
4285 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004286
Jamie Madille2e406c2016-06-02 13:04:10 -04004287 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004288 {
Jamie Madill437fa652016-05-03 15:13:24 -04004289 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004290 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4291 return false;
4292 }
4293
4294 // Check for invalid bits in the mask
4295 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4296 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4297 GL_MAP_UNSYNCHRONIZED_BIT;
4298
4299 if (access & ~(allAccessBits))
4300 {
Jamie Madill437fa652016-05-03 15:13:24 -04004301 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004302 return false;
4303 }
4304
4305 if (length == 0)
4306 {
Jamie Madill437fa652016-05-03 15:13:24 -04004307 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004308 return false;
4309 }
4310
4311 if (buffer->isMapped())
4312 {
Jamie Madill437fa652016-05-03 15:13:24 -04004313 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004314 return false;
4315 }
4316
4317 // Check for invalid bit combinations
4318 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4319 {
Jamie Madill437fa652016-05-03 15:13:24 -04004320 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004321 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4322 return false;
4323 }
4324
4325 GLbitfield writeOnlyBits =
4326 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4327
4328 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4329 {
Jamie Madill437fa652016-05-03 15:13:24 -04004330 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004331 "Invalid access bits when mapping buffer for reading: 0x%X.",
4332 access));
4333 return false;
4334 }
4335
4336 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4337 {
Jamie Madill437fa652016-05-03 15:13:24 -04004338 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004339 GL_INVALID_OPERATION,
4340 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4341 return false;
4342 }
4343 return true;
4344}
4345
4346bool ValidateFlushMappedBufferRangeBase(Context *context,
4347 GLenum target,
4348 GLintptr offset,
4349 GLsizeiptr length)
4350{
4351 if (offset < 0 || length < 0)
4352 {
Jamie Madill437fa652016-05-03 15:13:24 -04004353 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004354 return false;
4355 }
4356
4357 if (!ValidBufferTarget(context, target))
4358 {
Jamie Madill437fa652016-05-03 15:13:24 -04004359 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004360 return false;
4361 }
4362
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004363 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004364
4365 if (buffer == nullptr)
4366 {
Jamie Madill437fa652016-05-03 15:13:24 -04004367 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004368 return false;
4369 }
4370
4371 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4372 {
Jamie Madill437fa652016-05-03 15:13:24 -04004373 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004374 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4375 return false;
4376 }
4377
4378 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004379 CheckedNumeric<size_t> checkedOffset(offset);
4380 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004381
Jamie Madille2e406c2016-06-02 13:04:10 -04004382 if (!checkedSize.IsValid() ||
4383 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004384 {
Jamie Madill437fa652016-05-03 15:13:24 -04004385 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004386 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4387 return false;
4388 }
4389
4390 return true;
4391}
4392
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004393bool ValidateGenerateMipmap(Context *context, GLenum target)
4394{
4395 if (!ValidTextureTarget(context, target))
4396 {
4397 context->handleError(Error(GL_INVALID_ENUM));
4398 return false;
4399 }
4400
4401 Texture *texture = context->getTargetTexture(target);
4402
4403 if (texture == nullptr)
4404 {
4405 context->handleError(Error(GL_INVALID_OPERATION));
4406 return false;
4407 }
4408
4409 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4410
4411 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4412 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4413 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4414 {
4415 context->handleError(Error(GL_INVALID_OPERATION));
4416 return false;
4417 }
4418
Jamie Madilla3944d42016-07-22 22:13:26 -04004419 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4420 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4421 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004422
4423 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4424 // unsized formats or that are color renderable and filterable. Since we do not track if
4425 // the texture was created with sized or unsized format (only sized formats are stored),
4426 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4427 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4428 // textures since they're the only texture format that can be created with unsized formats
4429 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4430 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004431 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4432 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004433 {
4434 context->handleError(Error(GL_INVALID_OPERATION));
4435 return false;
4436 }
4437
4438 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004439 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004440 {
4441 context->handleError(Error(GL_INVALID_OPERATION));
4442 return false;
4443 }
4444
4445 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004446 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004447 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4448 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4449 {
Geoff Lang55482a12016-11-21 16:54:01 -05004450 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004451 context->handleError(Error(GL_INVALID_OPERATION));
4452 return false;
4453 }
4454
4455 // Cube completeness check
4456 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4457 {
4458 context->handleError(Error(GL_INVALID_OPERATION));
4459 return false;
4460 }
4461
4462 return true;
4463}
4464
Olli Etuaho41997e72016-03-10 13:38:39 +02004465bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4466{
4467 return ValidateGenOrDelete(context, n);
4468}
4469
4470bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4471{
4472 return ValidateGenOrDelete(context, n);
4473}
4474
4475bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4476{
4477 return ValidateGenOrDelete(context, n);
4478}
4479
4480bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4481{
4482 return ValidateGenOrDelete(context, n);
4483}
4484
4485bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4486{
4487 return ValidateGenOrDelete(context, n);
4488}
4489
4490bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4491{
4492 return ValidateGenOrDelete(context, n);
4493}
4494
4495bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4496{
4497 return ValidateGenOrDelete(context, n);
4498}
4499
4500bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4501{
4502 return ValidateGenOrDelete(context, n);
4503}
4504
4505bool ValidateGenOrDelete(Context *context, GLint n)
4506{
4507 if (n < 0)
4508 {
Jamie Madill437fa652016-05-03 15:13:24 -04004509 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004510 return false;
4511 }
4512 return true;
4513}
4514
Geoff Langf41a7152016-09-19 15:11:17 -04004515bool ValidateEnable(Context *context, GLenum cap)
4516{
4517 if (!ValidCap(context, cap, false))
4518 {
4519 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4520 return false;
4521 }
4522
4523 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4524 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4525 {
4526 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4527 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4528
4529 // We also output an error message to the debugger window if tracing is active, so that
4530 // developers can see the error message.
4531 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004532 return false;
4533 }
4534
4535 return true;
4536}
4537
4538bool ValidateDisable(Context *context, GLenum cap)
4539{
4540 if (!ValidCap(context, cap, false))
4541 {
4542 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4543 return false;
4544 }
4545
4546 return true;
4547}
4548
4549bool ValidateIsEnabled(Context *context, GLenum cap)
4550{
4551 if (!ValidCap(context, cap, true))
4552 {
4553 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4554 return false;
4555 }
4556
4557 return true;
4558}
4559
Geoff Langff5b2d52016-09-07 11:32:23 -04004560bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4561{
4562 if (!context->getExtensions().robustClientMemory)
4563 {
4564 context->handleError(
4565 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4566 return false;
4567 }
4568
4569 if (bufSize < 0)
4570 {
4571 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4572 return false;
4573 }
4574
4575 return true;
4576}
4577
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004578bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4579{
4580 if (bufSize < numParams)
4581 {
4582 context->handleError(Error(GL_INVALID_OPERATION,
4583 "%u parameters are required but %i were provided.", numParams,
4584 bufSize));
4585 return false;
4586 }
4587
4588 return true;
4589}
4590
Geoff Langff5b2d52016-09-07 11:32:23 -04004591bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4592 GLenum target,
4593 GLenum attachment,
4594 GLenum pname,
4595 GLsizei *numParams)
4596{
4597 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4598 *numParams = 1;
4599
4600 if (!ValidFramebufferTarget(target))
4601 {
4602 context->handleError(Error(GL_INVALID_ENUM));
4603 return false;
4604 }
4605
4606 int clientVersion = context->getClientMajorVersion();
4607
4608 switch (pname)
4609 {
4610 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4611 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4612 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4613 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4614 break;
4615
4616 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4617 if (clientVersion < 3 && !context->getExtensions().sRGB)
4618 {
4619 context->handleError(Error(GL_INVALID_ENUM));
4620 return false;
4621 }
4622 break;
4623
4624 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4625 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4626 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4627 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4628 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4629 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4630 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4631 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4632 if (clientVersion < 3)
4633 {
4634 context->handleError(Error(GL_INVALID_ENUM));
4635 return false;
4636 }
4637 break;
4638
4639 default:
4640 context->handleError(Error(GL_INVALID_ENUM));
4641 return false;
4642 }
4643
4644 // Determine if the attachment is a valid enum
4645 switch (attachment)
4646 {
4647 case GL_BACK:
4648 case GL_FRONT:
4649 case GL_DEPTH:
4650 case GL_STENCIL:
4651 case GL_DEPTH_STENCIL_ATTACHMENT:
4652 if (clientVersion < 3)
4653 {
4654 context->handleError(Error(GL_INVALID_ENUM));
4655 return false;
4656 }
4657 break;
4658
4659 case GL_DEPTH_ATTACHMENT:
4660 case GL_STENCIL_ATTACHMENT:
4661 break;
4662
4663 default:
4664 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4665 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4666 {
4667 context->handleError(Error(GL_INVALID_ENUM));
4668 return false;
4669 }
4670 break;
4671 }
4672
4673 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4674 ASSERT(framebuffer);
4675
4676 if (framebuffer->id() == 0)
4677 {
4678 if (clientVersion < 3)
4679 {
4680 context->handleError(Error(GL_INVALID_OPERATION));
4681 return false;
4682 }
4683
4684 switch (attachment)
4685 {
4686 case GL_BACK:
4687 case GL_DEPTH:
4688 case GL_STENCIL:
4689 break;
4690
4691 default:
4692 context->handleError(Error(GL_INVALID_OPERATION));
4693 return false;
4694 }
4695 }
4696 else
4697 {
4698 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4699 {
4700 // Valid attachment query
4701 }
4702 else
4703 {
4704 switch (attachment)
4705 {
4706 case GL_DEPTH_ATTACHMENT:
4707 case GL_STENCIL_ATTACHMENT:
4708 break;
4709
4710 case GL_DEPTH_STENCIL_ATTACHMENT:
4711 if (!framebuffer->hasValidDepthStencil())
4712 {
4713 context->handleError(Error(GL_INVALID_OPERATION));
4714 return false;
4715 }
4716 break;
4717
4718 default:
4719 context->handleError(Error(GL_INVALID_OPERATION));
4720 return false;
4721 }
4722 }
4723 }
4724
4725 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4726 if (attachmentObject)
4727 {
4728 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4729 attachmentObject->type() == GL_TEXTURE ||
4730 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4731
4732 switch (pname)
4733 {
4734 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4735 if (attachmentObject->type() != GL_RENDERBUFFER &&
4736 attachmentObject->type() != GL_TEXTURE)
4737 {
4738 context->handleError(Error(GL_INVALID_ENUM));
4739 return false;
4740 }
4741 break;
4742
4743 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4744 if (attachmentObject->type() != GL_TEXTURE)
4745 {
4746 context->handleError(Error(GL_INVALID_ENUM));
4747 return false;
4748 }
4749 break;
4750
4751 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4752 if (attachmentObject->type() != GL_TEXTURE)
4753 {
4754 context->handleError(Error(GL_INVALID_ENUM));
4755 return false;
4756 }
4757 break;
4758
4759 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4760 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4761 {
4762 context->handleError(Error(GL_INVALID_OPERATION));
4763 return false;
4764 }
4765 break;
4766
4767 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4768 if (attachmentObject->type() != GL_TEXTURE)
4769 {
4770 context->handleError(Error(GL_INVALID_ENUM));
4771 return false;
4772 }
4773 break;
4774
4775 default:
4776 break;
4777 }
4778 }
4779 else
4780 {
4781 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4782 // is NONE, then querying any other pname will generate INVALID_ENUM.
4783
4784 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4785 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4786 // INVALID_OPERATION for all other pnames
4787
4788 switch (pname)
4789 {
4790 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4791 break;
4792
4793 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4794 if (clientVersion < 3)
4795 {
4796 context->handleError(Error(GL_INVALID_ENUM));
4797 return false;
4798 }
4799 break;
4800
4801 default:
4802 if (clientVersion < 3)
4803 {
4804 context->handleError(Error(GL_INVALID_ENUM));
4805 return false;
4806 }
4807 else
4808 {
4809 context->handleError(Error(GL_INVALID_OPERATION));
4810 return false;
4811 }
4812 }
4813 }
4814
4815 return true;
4816}
4817
4818bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4819 GLenum target,
4820 GLenum attachment,
4821 GLenum pname,
4822 GLsizei bufSize,
4823 GLsizei *numParams)
4824{
4825 if (!ValidateRobustEntryPoint(context, bufSize))
4826 {
4827 return false;
4828 }
4829
4830 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4831 {
4832 return false;
4833 }
4834
4835 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4836 {
4837 return false;
4838 }
4839
4840 return true;
4841}
4842
4843bool ValidateGetBufferParameteriv(ValidationContext *context,
4844 GLenum target,
4845 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004846 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004847{
Geoff Langebebe1c2016-10-14 12:01:31 -04004848 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004849}
4850
4851bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4852 GLenum target,
4853 GLenum pname,
4854 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004855 GLsizei *length,
4856 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004857{
4858 if (!ValidateRobustEntryPoint(context, bufSize))
4859 {
4860 return false;
4861 }
4862
Geoff Langebebe1c2016-10-14 12:01:31 -04004863 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004864 {
4865 return false;
4866 }
4867
Geoff Langebebe1c2016-10-14 12:01:31 -04004868 if (!ValidateRobustBufferSize(context, bufSize, *length))
4869 {
4870 return false;
4871 }
4872
4873 return true;
4874}
4875
4876bool ValidateGetBufferParameteri64v(ValidationContext *context,
4877 GLenum target,
4878 GLenum pname,
4879 GLint64 *params)
4880{
4881 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4882}
4883
4884bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4885 GLenum target,
4886 GLenum pname,
4887 GLsizei bufSize,
4888 GLsizei *length,
4889 GLint64 *params)
4890{
4891 if (!ValidateRobustEntryPoint(context, bufSize))
4892 {
4893 return false;
4894 }
4895
4896 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4897 {
4898 return false;
4899 }
4900
4901 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004902 {
4903 return false;
4904 }
4905
4906 return true;
4907}
4908
4909bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4910{
4911 // Currently, all GetProgramiv queries return 1 parameter
4912 *numParams = 1;
4913
4914 Program *programObject = GetValidProgram(context, program);
4915 if (!programObject)
4916 {
4917 return false;
4918 }
4919
4920 switch (pname)
4921 {
4922 case GL_DELETE_STATUS:
4923 case GL_LINK_STATUS:
4924 case GL_VALIDATE_STATUS:
4925 case GL_INFO_LOG_LENGTH:
4926 case GL_ATTACHED_SHADERS:
4927 case GL_ACTIVE_ATTRIBUTES:
4928 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4929 case GL_ACTIVE_UNIFORMS:
4930 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4931 break;
4932
4933 case GL_PROGRAM_BINARY_LENGTH:
4934 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4935 {
4936 context->handleError(Error(GL_INVALID_ENUM,
4937 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4938 "GL_OES_get_program_binary or ES 3.0."));
4939 return false;
4940 }
4941 break;
4942
4943 case GL_ACTIVE_UNIFORM_BLOCKS:
4944 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4945 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4946 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4947 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4948 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4949 if (context->getClientMajorVersion() < 3)
4950 {
4951 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4952 return false;
4953 }
4954 break;
4955
4956 default:
4957 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4958 return false;
4959 }
4960
4961 return true;
4962}
4963
4964bool ValidateGetProgramivRobustANGLE(Context *context,
4965 GLuint program,
4966 GLenum pname,
4967 GLsizei bufSize,
4968 GLsizei *numParams)
4969{
4970 if (!ValidateRobustEntryPoint(context, bufSize))
4971 {
4972 return false;
4973 }
4974
4975 if (!ValidateGetProgramiv(context, program, pname, numParams))
4976 {
4977 return false;
4978 }
4979
4980 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4981 {
4982 return false;
4983 }
4984
4985 return true;
4986}
4987
Geoff Lang740d9022016-10-07 11:20:52 -04004988bool ValidateGetRenderbufferParameteriv(Context *context,
4989 GLenum target,
4990 GLenum pname,
4991 GLint *params)
4992{
4993 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4994}
4995
4996bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4997 GLenum target,
4998 GLenum pname,
4999 GLsizei bufSize,
5000 GLsizei *length,
5001 GLint *params)
5002{
5003 if (!ValidateRobustEntryPoint(context, bufSize))
5004 {
5005 return false;
5006 }
5007
5008 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
5009 {
5010 return false;
5011 }
5012
5013 if (!ValidateRobustBufferSize(context, bufSize, *length))
5014 {
5015 return false;
5016 }
5017
5018 return true;
5019}
5020
Geoff Langd7d0ed32016-10-07 11:33:51 -04005021bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
5022{
5023 return ValidateGetShaderivBase(context, shader, pname, nullptr);
5024}
5025
5026bool ValidateGetShaderivRobustANGLE(Context *context,
5027 GLuint shader,
5028 GLenum pname,
5029 GLsizei bufSize,
5030 GLsizei *length,
5031 GLint *params)
5032{
5033 if (!ValidateRobustEntryPoint(context, bufSize))
5034 {
5035 return false;
5036 }
5037
5038 if (!ValidateGetShaderivBase(context, shader, pname, length))
5039 {
5040 return false;
5041 }
5042
5043 if (!ValidateRobustBufferSize(context, bufSize, *length))
5044 {
5045 return false;
5046 }
5047
5048 return true;
5049}
5050
Geoff Langc1984ed2016-10-07 12:41:00 -04005051bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5052{
5053 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5054}
5055
5056bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5057 GLenum target,
5058 GLenum pname,
5059 GLsizei bufSize,
5060 GLsizei *length,
5061 GLfloat *params)
5062{
5063 if (!ValidateRobustEntryPoint(context, bufSize))
5064 {
5065 return false;
5066 }
5067
5068 if (!ValidateGetTexParameterBase(context, target, pname, length))
5069 {
5070 return false;
5071 }
5072
5073 if (!ValidateRobustBufferSize(context, bufSize, *length))
5074 {
5075 return false;
5076 }
5077
5078 return true;
5079}
5080
5081bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5082{
5083 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5084}
5085
5086bool ValidateGetTexParameterivRobustANGLE(Context *context,
5087 GLenum target,
5088 GLenum pname,
5089 GLsizei bufSize,
5090 GLsizei *length,
5091 GLint *params)
5092{
5093 if (!ValidateRobustEntryPoint(context, bufSize))
5094 {
5095 return false;
5096 }
5097
5098 if (!ValidateGetTexParameterBase(context, target, pname, length))
5099 {
5100 return false;
5101 }
5102
5103 if (!ValidateRobustBufferSize(context, bufSize, *length))
5104 {
5105 return false;
5106 }
5107
5108 return true;
5109}
5110
5111bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5112{
5113 return ValidateTexParameterBase(context, target, pname, -1, &param);
5114}
5115
5116bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5117{
5118 return ValidateTexParameterBase(context, target, pname, -1, params);
5119}
5120
5121bool ValidateTexParameterfvRobustANGLE(Context *context,
5122 GLenum target,
5123 GLenum pname,
5124 GLsizei bufSize,
5125 const GLfloat *params)
5126{
5127 if (!ValidateRobustEntryPoint(context, bufSize))
5128 {
5129 return false;
5130 }
5131
5132 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5133}
5134
5135bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5136{
5137 return ValidateTexParameterBase(context, target, pname, -1, &param);
5138}
5139
5140bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5141{
5142 return ValidateTexParameterBase(context, target, pname, -1, params);
5143}
5144
5145bool ValidateTexParameterivRobustANGLE(Context *context,
5146 GLenum target,
5147 GLenum pname,
5148 GLsizei bufSize,
5149 const GLint *params)
5150{
5151 if (!ValidateRobustEntryPoint(context, bufSize))
5152 {
5153 return false;
5154 }
5155
5156 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5157}
5158
5159bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5160{
5161 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5162}
5163
5164bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5165 GLuint sampler,
5166 GLenum pname,
5167 GLuint bufSize,
5168 GLsizei *length,
5169 GLfloat *params)
5170{
5171 if (!ValidateRobustEntryPoint(context, bufSize))
5172 {
5173 return false;
5174 }
5175
5176 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5177 {
5178 return false;
5179 }
5180
5181 if (!ValidateRobustBufferSize(context, bufSize, *length))
5182 {
5183 return false;
5184 }
5185
5186 return true;
5187}
5188
5189bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5190{
5191 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5192}
5193
5194bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5195 GLuint sampler,
5196 GLenum pname,
5197 GLuint bufSize,
5198 GLsizei *length,
5199 GLint *params)
5200{
5201 if (!ValidateRobustEntryPoint(context, bufSize))
5202 {
5203 return false;
5204 }
5205
5206 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5207 {
5208 return false;
5209 }
5210
5211 if (!ValidateRobustBufferSize(context, bufSize, *length))
5212 {
5213 return false;
5214 }
5215
5216 return true;
5217}
5218
5219bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5220{
5221 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5222}
5223
5224bool ValidateSamplerParameterfv(Context *context,
5225 GLuint sampler,
5226 GLenum pname,
5227 const GLfloat *params)
5228{
5229 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5230}
5231
5232bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5233 GLuint sampler,
5234 GLenum pname,
5235 GLsizei bufSize,
5236 const GLfloat *params)
5237{
5238 if (!ValidateRobustEntryPoint(context, bufSize))
5239 {
5240 return false;
5241 }
5242
5243 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5244}
5245
5246bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5247{
5248 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5249}
5250
5251bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5252{
5253 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5254}
5255
5256bool ValidateSamplerParameterivRobustANGLE(Context *context,
5257 GLuint sampler,
5258 GLenum pname,
5259 GLsizei bufSize,
5260 const GLint *params)
5261{
5262 if (!ValidateRobustEntryPoint(context, bufSize))
5263 {
5264 return false;
5265 }
5266
5267 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5268}
5269
Geoff Lang0b031062016-10-13 14:30:04 -04005270bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5271{
5272 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5273}
5274
5275bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5276 GLuint index,
5277 GLenum pname,
5278 GLsizei bufSize,
5279 GLsizei *length,
5280 GLfloat *params)
5281{
5282 if (!ValidateRobustEntryPoint(context, bufSize))
5283 {
5284 return false;
5285 }
5286
5287 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5288 {
5289 return false;
5290 }
5291
5292 if (!ValidateRobustBufferSize(context, bufSize, *length))
5293 {
5294 return false;
5295 }
5296
5297 return true;
5298}
5299
5300bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5301{
5302 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5303}
5304
5305bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5306 GLuint index,
5307 GLenum pname,
5308 GLsizei bufSize,
5309 GLsizei *length,
5310 GLint *params)
5311{
5312 if (!ValidateRobustEntryPoint(context, bufSize))
5313 {
5314 return false;
5315 }
5316
5317 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5318 {
5319 return false;
5320 }
5321
5322 if (!ValidateRobustBufferSize(context, bufSize, *length))
5323 {
5324 return false;
5325 }
5326
5327 return true;
5328}
5329
5330bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5331{
5332 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5333}
5334
5335bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5336 GLuint index,
5337 GLenum pname,
5338 GLsizei bufSize,
5339 GLsizei *length,
5340 void **pointer)
5341{
5342 if (!ValidateRobustEntryPoint(context, bufSize))
5343 {
5344 return false;
5345 }
5346
5347 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5348 {
5349 return false;
5350 }
5351
5352 if (!ValidateRobustBufferSize(context, bufSize, *length))
5353 {
5354 return false;
5355 }
5356
5357 return true;
5358}
5359
5360bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5361{
5362 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5363}
5364
5365bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5366 GLuint index,
5367 GLenum pname,
5368 GLsizei bufSize,
5369 GLsizei *length,
5370 GLint *params)
5371{
5372 if (!ValidateRobustEntryPoint(context, bufSize))
5373 {
5374 return false;
5375 }
5376
5377 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5378 {
5379 return false;
5380 }
5381
5382 if (!ValidateRobustBufferSize(context, bufSize, *length))
5383 {
5384 return false;
5385 }
5386
5387 return true;
5388}
5389
5390bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5391{
5392 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5393}
5394
5395bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5396 GLuint index,
5397 GLenum pname,
5398 GLsizei bufSize,
5399 GLsizei *length,
5400 GLuint *params)
5401{
5402 if (!ValidateRobustEntryPoint(context, bufSize))
5403 {
5404 return false;
5405 }
5406
5407 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5408 {
5409 return false;
5410 }
5411
5412 if (!ValidateRobustBufferSize(context, bufSize, *length))
5413 {
5414 return false;
5415 }
5416
5417 return true;
5418}
5419
Geoff Lang6899b872016-10-14 11:30:13 -04005420bool ValidateGetActiveUniformBlockiv(Context *context,
5421 GLuint program,
5422 GLuint uniformBlockIndex,
5423 GLenum pname,
5424 GLint *params)
5425{
5426 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5427}
5428
5429bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5430 GLuint program,
5431 GLuint uniformBlockIndex,
5432 GLenum pname,
5433 GLsizei bufSize,
5434 GLsizei *length,
5435 GLint *params)
5436{
5437 if (!ValidateRobustEntryPoint(context, bufSize))
5438 {
5439 return false;
5440 }
5441
5442 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5443 {
5444 return false;
5445 }
5446
5447 if (!ValidateRobustBufferSize(context, bufSize, *length))
5448 {
5449 return false;
5450 }
5451
5452 return true;
5453}
5454
Geoff Lang0a9661f2016-10-20 10:59:20 -07005455bool ValidateGetInternalFormativ(Context *context,
5456 GLenum target,
5457 GLenum internalformat,
5458 GLenum pname,
5459 GLsizei bufSize,
5460 GLint *params)
5461{
5462 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5463 nullptr);
5464}
5465
5466bool ValidateGetInternalFormativRobustANGLE(Context *context,
5467 GLenum target,
5468 GLenum internalformat,
5469 GLenum pname,
5470 GLsizei bufSize,
5471 GLsizei *length,
5472 GLint *params)
5473{
5474 if (!ValidateRobustEntryPoint(context, bufSize))
5475 {
5476 return false;
5477 }
5478
5479 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5480 {
5481 return false;
5482 }
5483
5484 if (!ValidateRobustBufferSize(context, bufSize, *length))
5485 {
5486 return false;
5487 }
5488
5489 return true;
5490}
5491
Jamie Madillc29968b2016-01-20 11:17:23 -05005492} // namespace gl