blob: 7c24fb2c216af65a0861c7201ee7501219645ecb [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
He Yunchaoced53ae2016-11-29 15:00:51 +080045 const VertexArray *vao = state.getVertexArray();
46 const auto &vertexAttribs = vao->getVertexAttributes();
47 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040048 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
49 {
50 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill63805b42015-08-25 13:17:39 -040051 if (program->isAttribLocationActive(attributeIndex) && attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040052 {
53 gl::Buffer *buffer = attrib.buffer.get();
54
55 if (buffer)
56 {
Corentin Wallez92db6942016-12-09 13:10:36 -050057 CheckedNumeric<GLint64> maxVertexElement = 0;
58 bool readsData = false;
59 if (attrib.divisor == 0)
Jamie Madill1ca74672015-07-21 15:14:11 -040060 {
Corentin Wallez92db6942016-12-09 13:10:36 -050061 readsData = vertexCount > 0;
Jamie Madill1ca74672015-07-21 15:14:11 -040062 maxVertexElement = static_cast<GLint64>(maxVertex);
63 }
Corentin Wallez92db6942016-12-09 13:10:36 -050064 else if (primcount > 0)
65 {
66 readsData = true;
67 maxVertexElement =
68 static_cast<GLint64>(primcount - 1) / static_cast<GLint64>(attrib.divisor);
69 }
Jamie Madill1ca74672015-07-21 15:14:11 -040070
71 // If we're drawing zero vertices, we have enough data.
Corentin Wallez92db6942016-12-09 13:10:36 -050072 if (readsData)
Jamie Madill1ca74672015-07-21 15:14:11 -040073 {
74 // Note: Last vertex element does not take the full stride!
Corentin Wallez92db6942016-12-09 13:10:36 -050075 CheckedNumeric<GLint64> attribStride = ComputeVertexAttributeStride(attrib);
76 CheckedNumeric<GLint64> attribSize = ComputeVertexAttributeTypeSize(attrib);
77 CheckedNumeric<GLint64> attribDataSize =
78 maxVertexElement * attribStride + attribSize;
79 CheckedNumeric<GLint64> maxOffset = attribDataSize + attrib.offset;
80
81 if (!maxOffset.IsValid())
82 {
83 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
84 return false;
85 }
Jamie Madill1ca74672015-07-21 15:14:11 -040086
87 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
88 // We can return INVALID_OPERATION if our vertex attribute does not have
89 // enough backing data.
Corentin Wallez92db6942016-12-09 13:10:36 -050090 if (maxOffset.ValueOrDie() > buffer->getSize())
Jamie Madill1ca74672015-07-21 15:14:11 -040091 {
Jamie Madill437fa652016-05-03 15:13:24 -040092 context->handleError(
Jamie Madillbc4c4bc2016-03-23 21:04:43 -040093 Error(GL_INVALID_OPERATION,
94 "Vertex buffer is not big enough for the draw call"));
Jamie Madill1ca74672015-07-21 15:14:11 -040095 return false;
96 }
97 }
98 }
99 else if (attrib.pointer == NULL)
100 {
101 // This is an application error that would normally result in a crash,
102 // but we catch it and return an error
Jamie Madill437fa652016-05-03 15:13:24 -0400103 context->handleError(Error(
Jamie Madill1ca74672015-07-21 15:14:11 -0400104 GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer."));
105 return false;
106 }
107 }
108 }
109
110 return true;
111}
112
Geoff Langf607c602016-09-21 11:46:48 -0400113bool ValidReadPixelsFormatType(ValidationContext *context,
114 GLenum framebufferComponentType,
115 GLenum format,
116 GLenum type)
117{
118 switch (framebufferComponentType)
119 {
120 case GL_UNSIGNED_NORMALIZED:
121 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
122 // ReadPixels with BGRA even if the extension is not present
123 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
124 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
125 type == GL_UNSIGNED_BYTE);
126
127 case GL_SIGNED_NORMALIZED:
128 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
129
130 case GL_INT:
131 return (format == GL_RGBA_INTEGER && type == GL_INT);
132
133 case GL_UNSIGNED_INT:
134 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
135
136 case GL_FLOAT:
137 return (format == GL_RGBA && type == GL_FLOAT);
138
139 default:
140 UNREACHABLE();
141 return false;
142 }
143}
144
Geoff Langf41a7152016-09-19 15:11:17 -0400145bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
Geoff Lang0550d032014-01-30 11:29:07 -0500146{
147 switch (cap)
148 {
Geoff Langf41a7152016-09-19 15:11:17 -0400149 // EXT_multisample_compatibility
150 case GL_MULTISAMPLE_EXT:
151 case GL_SAMPLE_ALPHA_TO_ONE_EXT:
152 return context->getExtensions().multisampleCompatibility;
Sami Väisänen74c23472016-05-09 17:30:30 +0300153
Geoff Langf41a7152016-09-19 15:11:17 -0400154 case GL_CULL_FACE:
155 case GL_POLYGON_OFFSET_FILL:
156 case GL_SAMPLE_ALPHA_TO_COVERAGE:
157 case GL_SAMPLE_COVERAGE:
158 case GL_SCISSOR_TEST:
159 case GL_STENCIL_TEST:
160 case GL_DEPTH_TEST:
161 case GL_BLEND:
162 case GL_DITHER:
163 return true;
Geoff Lang70d0f492015-12-10 17:45:46 -0500164
Geoff Langf41a7152016-09-19 15:11:17 -0400165 case GL_PRIMITIVE_RESTART_FIXED_INDEX:
166 case GL_RASTERIZER_DISCARD:
167 return (context->getClientMajorVersion() >= 3);
Geoff Lang70d0f492015-12-10 17:45:46 -0500168
Geoff Langf41a7152016-09-19 15:11:17 -0400169 case GL_DEBUG_OUTPUT_SYNCHRONOUS:
170 case GL_DEBUG_OUTPUT:
171 return context->getExtensions().debug;
Geoff Lang70d0f492015-12-10 17:45:46 -0500172
Geoff Langf41a7152016-09-19 15:11:17 -0400173 case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
174 return queryOnly && context->getExtensions().bindGeneratesResource;
175
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700176 case GL_FRAMEBUFFER_SRGB_EXT:
177 return context->getExtensions().sRGBWriteControl;
178
Geoff Lang3b573612016-10-31 14:08:10 -0400179 case GL_SAMPLE_MASK:
Geoff Lang3b573612016-10-31 14:08:10 -0400180 return context->getClientVersion() >= Version(3, 1);
181
Geoff Langf41a7152016-09-19 15:11:17 -0400182 default:
183 return false;
Geoff Lang0550d032014-01-30 11:29:07 -0500184 }
185}
186
Geoff Lang62fce5b2016-09-30 10:46:35 -0400187bool ValidateReadPixelsBase(ValidationContext *context,
188 GLint x,
189 GLint y,
190 GLsizei width,
191 GLsizei height,
192 GLenum format,
193 GLenum type,
194 GLsizei bufSize,
195 GLsizei *length,
196 GLvoid *pixels)
197{
198 if (length != nullptr)
199 {
200 *length = 0;
201 }
202
203 if (width < 0 || height < 0)
204 {
205 context->handleError(Error(GL_INVALID_VALUE, "width and height must be positive"));
206 return false;
207 }
208
209 auto readFramebuffer = context->getGLState().getReadFramebuffer();
210
211 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
212 {
213 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
214 return false;
215 }
216
217 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
218 {
219 context->handleError(Error(GL_INVALID_OPERATION));
220 return false;
221 }
222
223 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
224 ASSERT(framebuffer);
225
226 if (framebuffer->getReadBufferState() == GL_NONE)
227 {
228 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
229 return false;
230 }
231
232 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
233 if (!readBuffer)
234 {
235 context->handleError(Error(GL_INVALID_OPERATION));
236 return false;
237 }
238
239 GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
240 GLenum currentType = framebuffer->getImplementationColorReadType();
241 GLenum currentInternalFormat = readBuffer->getFormat().asSized();
242
243 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
244 bool validFormatTypeCombination =
245 ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
246
247 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
248 {
249 context->handleError(Error(GL_INVALID_OPERATION));
250 return false;
251 }
252
253 // Check for pixel pack buffer related API errors
254 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
255 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
256 {
257 // ...the buffer object's data store is currently mapped.
258 context->handleError(Error(GL_INVALID_OPERATION, "Pixel pack buffer is mapped."));
259 return false;
260 }
261
262 // .. the data would be packed to the buffer object such that the memory writes required
263 // would exceed the data store size.
264 GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
265 const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
266 const gl::Extents size(width, height, 1);
267 const auto &pack = context->getGLState().getPackState();
268
269 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
270 if (endByteOrErr.isError())
271 {
272 context->handleError(endByteOrErr.getError());
273 return false;
274 }
275
276 size_t endByte = endByteOrErr.getResult();
277 if (bufSize >= 0)
278 {
279
280 if (static_cast<size_t>(bufSize) < endByte)
281 {
282 context->handleError(
283 Error(GL_INVALID_OPERATION, "bufSize must be at least %u bytes.", endByte));
284 return false;
285 }
286 }
287
288 if (pixelPackBuffer != nullptr)
289 {
290 CheckedNumeric<size_t> checkedEndByte(endByte);
291 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
292 checkedEndByte += checkedOffset;
293
294 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
295 {
296 // Overflow past the end of the buffer
297 context->handleError(
298 Error(GL_INVALID_OPERATION, "Writes would overflow the pixel pack buffer."));
299 return false;
300 }
301 }
302
303 if (length != nullptr)
304 {
305 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
306 {
307 context->handleError(
308 Error(GL_INVALID_OPERATION, "length would overflow GLsizei.", endByte));
309 return false;
310 }
311
312 *length = static_cast<GLsizei>(endByte);
313 }
314
315 return true;
316}
317
Geoff Lang740d9022016-10-07 11:20:52 -0400318bool ValidateGetRenderbufferParameterivBase(Context *context,
319 GLenum target,
320 GLenum pname,
321 GLsizei *length)
322{
323 if (length)
324 {
325 *length = 0;
326 }
327
328 if (target != GL_RENDERBUFFER)
329 {
330 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
331 return false;
332 }
333
334 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
335 if (renderbuffer == nullptr)
336 {
337 context->handleError(Error(GL_INVALID_OPERATION, "No renderbuffer bound."));
338 return false;
339 }
340
341 switch (pname)
342 {
343 case GL_RENDERBUFFER_WIDTH:
344 case GL_RENDERBUFFER_HEIGHT:
345 case GL_RENDERBUFFER_INTERNAL_FORMAT:
346 case GL_RENDERBUFFER_RED_SIZE:
347 case GL_RENDERBUFFER_GREEN_SIZE:
348 case GL_RENDERBUFFER_BLUE_SIZE:
349 case GL_RENDERBUFFER_ALPHA_SIZE:
350 case GL_RENDERBUFFER_DEPTH_SIZE:
351 case GL_RENDERBUFFER_STENCIL_SIZE:
352 break;
353
354 case GL_RENDERBUFFER_SAMPLES_ANGLE:
355 if (!context->getExtensions().framebufferMultisample)
356 {
357 context->handleError(
358 Error(GL_INVALID_ENUM, "GL_ANGLE_framebuffer_multisample is not enabled."));
359 return false;
360 }
361 break;
362
363 default:
364 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
365 return false;
366 }
367
368 if (length)
369 {
370 *length = 1;
371 }
372 return true;
373}
374
Geoff Langd7d0ed32016-10-07 11:33:51 -0400375bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
376{
377 if (length)
378 {
379 *length = 0;
380 }
381
382 if (GetValidShader(context, shader) == nullptr)
383 {
384 return false;
385 }
386
387 switch (pname)
388 {
389 case GL_SHADER_TYPE:
390 case GL_DELETE_STATUS:
391 case GL_COMPILE_STATUS:
392 case GL_INFO_LOG_LENGTH:
393 case GL_SHADER_SOURCE_LENGTH:
394 break;
395
396 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
397 if (!context->getExtensions().translatedShaderSource)
398 {
399 context->handleError(
400 Error(GL_INVALID_ENUM, "GL_ANGLE_translated_shader_source is not enabled."));
401 return false;
402 }
403 break;
404
405 default:
406 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
407 return false;
408 }
409
410 if (length)
411 {
412 *length = 1;
413 }
414 return true;
415}
416
Geoff Langc1984ed2016-10-07 12:41:00 -0400417bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
418{
419 if (length)
420 {
421 *length = 0;
422 }
423
424 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
425 {
426 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
427 return false;
428 }
429
430 if (context->getTargetTexture(target) == nullptr)
431 {
432 // Should only be possible for external textures
433 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
434 return false;
435 }
436
437 switch (pname)
438 {
439 case GL_TEXTURE_MAG_FILTER:
440 case GL_TEXTURE_MIN_FILTER:
441 case GL_TEXTURE_WRAP_S:
442 case GL_TEXTURE_WRAP_T:
443 break;
444
445 case GL_TEXTURE_USAGE_ANGLE:
446 if (!context->getExtensions().textureUsage)
447 {
448 context->handleError(
449 Error(GL_INVALID_ENUM, "GL_ANGLE_texture_usage is not enabled."));
450 return false;
451 }
452 break;
453
454 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
455 if (!context->getExtensions().textureFilterAnisotropic)
456 {
457 context->handleError(
458 Error(GL_INVALID_ENUM, "GL_EXT_texture_filter_anisotropic is not enabled."));
459 return false;
460 }
461 break;
462
463 case GL_TEXTURE_IMMUTABLE_FORMAT:
464 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
465 {
466 context->handleError(
467 Error(GL_INVALID_ENUM, "GL_EXT_texture_storage is not enabled."));
468 return false;
469 }
470 break;
471
472 case GL_TEXTURE_WRAP_R:
473 case GL_TEXTURE_IMMUTABLE_LEVELS:
474 case GL_TEXTURE_SWIZZLE_R:
475 case GL_TEXTURE_SWIZZLE_G:
476 case GL_TEXTURE_SWIZZLE_B:
477 case GL_TEXTURE_SWIZZLE_A:
478 case GL_TEXTURE_BASE_LEVEL:
479 case GL_TEXTURE_MAX_LEVEL:
480 case GL_TEXTURE_MIN_LOD:
481 case GL_TEXTURE_MAX_LOD:
482 case GL_TEXTURE_COMPARE_MODE:
483 case GL_TEXTURE_COMPARE_FUNC:
484 if (context->getClientMajorVersion() < 3)
485 {
486 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
487 return false;
488 }
489 break;
490
Geoff Lang81c6b572016-10-19 14:07:52 -0700491 case GL_TEXTURE_SRGB_DECODE_EXT:
492 if (!context->getExtensions().textureSRGBDecode)
493 {
494 context->handleError(
495 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
496 return false;
497 }
498 break;
499
Geoff Langc1984ed2016-10-07 12:41:00 -0400500 default:
501 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
502 return false;
503 }
504
505 if (length)
506 {
507 *length = 1;
508 }
509 return true;
510}
511
512template <typename ParamType>
513bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
514{
515 switch (ConvertToGLenum(params[0]))
516 {
517 case GL_CLAMP_TO_EDGE:
518 break;
519
520 case GL_REPEAT:
521 case GL_MIRRORED_REPEAT:
522 if (isExternalTextureTarget)
523 {
524 // OES_EGL_image_external specifies this error.
525 context->handleError(Error(
526 GL_INVALID_ENUM, "external textures only support CLAMP_TO_EDGE wrap mode"));
527 return false;
528 }
529 break;
530
531 default:
532 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
533 return false;
534 }
535
536 return true;
537}
538
539template <typename ParamType>
540bool ValidateTextureMinFilterValue(Context *context,
541 ParamType *params,
542 bool isExternalTextureTarget)
543{
544 switch (ConvertToGLenum(params[0]))
545 {
546 case GL_NEAREST:
547 case GL_LINEAR:
548 break;
549
550 case GL_NEAREST_MIPMAP_NEAREST:
551 case GL_LINEAR_MIPMAP_NEAREST:
552 case GL_NEAREST_MIPMAP_LINEAR:
553 case GL_LINEAR_MIPMAP_LINEAR:
554 if (isExternalTextureTarget)
555 {
556 // OES_EGL_image_external specifies this error.
557 context->handleError(
558 Error(GL_INVALID_ENUM,
559 "external textures only support NEAREST and LINEAR filtering"));
560 return false;
561 }
562 break;
563
564 default:
565 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
566 return false;
567 }
568
569 return true;
570}
571
572template <typename ParamType>
573bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
574{
575 switch (ConvertToGLenum(params[0]))
576 {
577 case GL_NEAREST:
578 case GL_LINEAR:
579 break;
580
581 default:
582 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
583 return false;
584 }
585
586 return true;
587}
588
589template <typename ParamType>
590bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
591{
592 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
593 switch (ConvertToGLenum(params[0]))
594 {
595 case GL_NONE:
596 case GL_COMPARE_REF_TO_TEXTURE:
597 break;
598
599 default:
600 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
601 return false;
602 }
603
604 return true;
605}
606
607template <typename ParamType>
608bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
609{
610 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
611 switch (ConvertToGLenum(params[0]))
612 {
613 case GL_LEQUAL:
614 case GL_GEQUAL:
615 case GL_LESS:
616 case GL_GREATER:
617 case GL_EQUAL:
618 case GL_NOTEQUAL:
619 case GL_ALWAYS:
620 case GL_NEVER:
621 break;
622
623 default:
624 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
625 return false;
626 }
627
628 return true;
629}
630
631template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700632bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
633{
634 if (!context->getExtensions().textureSRGBDecode)
635 {
636 context->handleError(Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
637 return false;
638 }
639
640 switch (ConvertToGLenum(params[0]))
641 {
642 case GL_DECODE_EXT:
643 case GL_SKIP_DECODE_EXT:
644 break;
645
646 default:
647 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
648 return false;
649 }
650
651 return true;
652}
653
654template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400655bool ValidateTexParameterBase(Context *context,
656 GLenum target,
657 GLenum pname,
658 GLsizei bufSize,
659 ParamType *params)
660{
661 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
662 {
663 context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
664 return false;
665 }
666
667 if (context->getTargetTexture(target) == nullptr)
668 {
669 // Should only be possible for external textures
670 context->handleError(Error(GL_INVALID_ENUM, "No texture bound."));
671 return false;
672 }
673
674 const GLsizei minBufSize = 1;
675 if (bufSize >= 0 && bufSize < minBufSize)
676 {
677 context->handleError(
678 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
679 return false;
680 }
681
682 switch (pname)
683 {
684 case GL_TEXTURE_WRAP_R:
685 case GL_TEXTURE_SWIZZLE_R:
686 case GL_TEXTURE_SWIZZLE_G:
687 case GL_TEXTURE_SWIZZLE_B:
688 case GL_TEXTURE_SWIZZLE_A:
689 case GL_TEXTURE_BASE_LEVEL:
690 case GL_TEXTURE_MAX_LEVEL:
691 case GL_TEXTURE_COMPARE_MODE:
692 case GL_TEXTURE_COMPARE_FUNC:
693 case GL_TEXTURE_MIN_LOD:
694 case GL_TEXTURE_MAX_LOD:
695 if (context->getClientMajorVersion() < 3)
696 {
697 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
698 return false;
699 }
700 if (target == GL_TEXTURE_EXTERNAL_OES &&
701 !context->getExtensions().eglImageExternalEssl3)
702 {
703 context->handleError(Error(GL_INVALID_ENUM,
704 "ES3 texture parameters are not available without "
705 "GL_OES_EGL_image_external_essl3."));
706 return false;
707 }
708 break;
709
710 default:
711 break;
712 }
713
714 switch (pname)
715 {
716 case GL_TEXTURE_WRAP_S:
717 case GL_TEXTURE_WRAP_T:
718 case GL_TEXTURE_WRAP_R:
719 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
720 {
721 return false;
722 }
723 break;
724
725 case GL_TEXTURE_MIN_FILTER:
726 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
727 {
728 return false;
729 }
730 break;
731
732 case GL_TEXTURE_MAG_FILTER:
733 if (!ValidateTextureMagFilterValue(context, params))
734 {
735 return false;
736 }
737 break;
738
739 case GL_TEXTURE_USAGE_ANGLE:
740 switch (ConvertToGLenum(params[0]))
741 {
742 case GL_NONE:
743 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
744 break;
745
746 default:
747 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
748 return false;
749 }
750 break;
751
752 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
753 if (!context->getExtensions().textureFilterAnisotropic)
754 {
755 context->handleError(
756 Error(GL_INVALID_ENUM, "GL_EXT_texture_anisotropic is not enabled."));
757 return false;
758 }
759
760 // we assume the parameter passed to this validation method is truncated, not rounded
761 if (params[0] < 1)
762 {
763 context->handleError(Error(GL_INVALID_VALUE, "Max anisotropy must be at least 1."));
764 return false;
765 }
766 break;
767
768 case GL_TEXTURE_MIN_LOD:
769 case GL_TEXTURE_MAX_LOD:
770 // any value is permissible
771 break;
772
773 case GL_TEXTURE_COMPARE_MODE:
774 if (!ValidateTextureCompareModeValue(context, params))
775 {
776 return false;
777 }
778 break;
779
780 case GL_TEXTURE_COMPARE_FUNC:
781 if (!ValidateTextureCompareFuncValue(context, params))
782 {
783 return false;
784 }
785 break;
786
787 case GL_TEXTURE_SWIZZLE_R:
788 case GL_TEXTURE_SWIZZLE_G:
789 case GL_TEXTURE_SWIZZLE_B:
790 case GL_TEXTURE_SWIZZLE_A:
791 switch (ConvertToGLenum(params[0]))
792 {
793 case GL_RED:
794 case GL_GREEN:
795 case GL_BLUE:
796 case GL_ALPHA:
797 case GL_ZERO:
798 case GL_ONE:
799 break;
800
801 default:
802 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
803 return false;
804 }
805 break;
806
807 case GL_TEXTURE_BASE_LEVEL:
808 if (params[0] < 0)
809 {
810 context->handleError(Error(GL_INVALID_VALUE, "Base level must be at least 0."));
811 return false;
812 }
813 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
814 {
815 context->handleError(
816 Error(GL_INVALID_OPERATION, "Base level must be 0 for external textures."));
817 return false;
818 }
819 break;
820
821 case GL_TEXTURE_MAX_LEVEL:
822 if (params[0] < 0)
823 {
824 context->handleError(Error(GL_INVALID_VALUE, "Max level must be at least 0."));
825 return false;
826 }
827 break;
828
Geoff Lang3b573612016-10-31 14:08:10 -0400829 case GL_DEPTH_STENCIL_TEXTURE_MODE:
830 if (context->getClientVersion() < Version(3, 1))
831 {
832 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.1."));
833 return false;
834 }
Geoff Lang9f090372016-12-02 10:20:43 -0500835 switch (ConvertToGLenum(params[0]))
836 {
837 case GL_DEPTH_COMPONENT:
838 case GL_STENCIL_INDEX:
839 break;
840
841 default:
842 context->handleError(Error(GL_INVALID_ENUM, "Unknown param value."));
843 return false;
844 }
Geoff Lang3b573612016-10-31 14:08:10 -0400845 break;
846
Geoff Lang81c6b572016-10-19 14:07:52 -0700847 case GL_TEXTURE_SRGB_DECODE_EXT:
848 if (!ValidateTextureSRGBDecodeValue(context, params))
849 {
850 return false;
851 }
852 break;
853
Geoff Langc1984ed2016-10-07 12:41:00 -0400854 default:
855 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
856 return false;
857 }
858
859 return true;
860}
861
862template <typename ParamType>
863bool ValidateSamplerParameterBase(Context *context,
864 GLuint sampler,
865 GLenum pname,
866 GLsizei bufSize,
867 ParamType *params)
868{
869 if (context->getClientMajorVersion() < 3)
870 {
871 context->handleError(
872 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
873 return false;
874 }
875
876 if (!context->isSampler(sampler))
877 {
878 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
879 return false;
880 }
881
882 const GLsizei minBufSize = 1;
883 if (bufSize >= 0 && bufSize < minBufSize)
884 {
885 context->handleError(
886 Error(GL_INVALID_OPERATION, "bufSize must be at least %i.", minBufSize));
887 return false;
888 }
889
890 switch (pname)
891 {
892 case GL_TEXTURE_WRAP_S:
893 case GL_TEXTURE_WRAP_T:
894 case GL_TEXTURE_WRAP_R:
895 if (!ValidateTextureWrapModeValue(context, params, false))
896 {
897 return false;
898 }
899 break;
900
901 case GL_TEXTURE_MIN_FILTER:
902 if (!ValidateTextureMinFilterValue(context, params, false))
903 {
904 return false;
905 }
906 break;
907
908 case GL_TEXTURE_MAG_FILTER:
909 if (!ValidateTextureMagFilterValue(context, params))
910 {
911 return false;
912 }
913 break;
914
915 case GL_TEXTURE_MIN_LOD:
916 case GL_TEXTURE_MAX_LOD:
917 // any value is permissible
918 break;
919
920 case GL_TEXTURE_COMPARE_MODE:
921 if (!ValidateTextureCompareModeValue(context, params))
922 {
923 return false;
924 }
925 break;
926
927 case GL_TEXTURE_COMPARE_FUNC:
928 if (!ValidateTextureCompareFuncValue(context, params))
929 {
930 return false;
931 }
932 break;
933
Geoff Lang81c6b572016-10-19 14:07:52 -0700934 case GL_TEXTURE_SRGB_DECODE_EXT:
935 if (!ValidateTextureSRGBDecodeValue(context, params))
936 {
937 return false;
938 }
939 break;
940
Geoff Langc1984ed2016-10-07 12:41:00 -0400941 default:
942 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
943 return false;
944 }
945
946 return true;
947}
948
949bool ValidateGetSamplerParameterBase(Context *context,
950 GLuint sampler,
951 GLenum pname,
952 GLsizei *length)
953{
954 if (length)
955 {
956 *length = 0;
957 }
958
959 if (context->getClientMajorVersion() < 3)
960 {
961 context->handleError(
962 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
963 return false;
964 }
965
966 if (!context->isSampler(sampler))
967 {
968 context->handleError(Error(GL_INVALID_OPERATION, "Sampler is not valid."));
969 return false;
970 }
971
972 switch (pname)
973 {
974 case GL_TEXTURE_WRAP_S:
975 case GL_TEXTURE_WRAP_T:
976 case GL_TEXTURE_WRAP_R:
977 case GL_TEXTURE_MIN_FILTER:
978 case GL_TEXTURE_MAG_FILTER:
979 case GL_TEXTURE_MIN_LOD:
980 case GL_TEXTURE_MAX_LOD:
981 case GL_TEXTURE_COMPARE_MODE:
982 case GL_TEXTURE_COMPARE_FUNC:
983 break;
984
Geoff Lang81c6b572016-10-19 14:07:52 -0700985 case GL_TEXTURE_SRGB_DECODE_EXT:
986 if (!context->getExtensions().textureSRGBDecode)
987 {
988 context->handleError(
989 Error(GL_INVALID_ENUM, "GL_EXT_texture_sRGB_decode is not enabled."));
990 return false;
991 }
992 break;
993
Geoff Langc1984ed2016-10-07 12:41:00 -0400994 default:
995 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
996 return false;
997 }
998
999 if (length)
1000 {
1001 *length = 1;
1002 }
1003 return true;
1004}
1005
Geoff Lang0b031062016-10-13 14:30:04 -04001006bool ValidateGetVertexAttribBase(Context *context,
1007 GLuint index,
1008 GLenum pname,
1009 GLsizei *length,
1010 bool pointer,
1011 bool pureIntegerEntryPoint)
1012{
1013 if (length)
1014 {
1015 *length = 0;
1016 }
1017
1018 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
1019 {
1020 context->handleError(
1021 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1022 return false;
1023 }
1024
1025 if (index >= context->getCaps().maxVertexAttributes)
1026 {
1027 context->handleError(Error(
1028 GL_INVALID_VALUE, "index must be less than the value of GL_MAX_VERTEX_ATTRIBUTES."));
1029 return false;
1030 }
1031
1032 if (pointer)
1033 {
1034 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
1035 {
1036 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1037 return false;
1038 }
1039 }
1040 else
1041 {
1042 switch (pname)
1043 {
1044 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
1045 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
1046 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
1047 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
1048 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
1049 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
1050 case GL_CURRENT_VERTEX_ATTRIB:
1051 break;
1052
1053 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
1054 static_assert(
1055 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
1056 "ANGLE extension enums not equal to GL enums.");
1057 if (context->getClientMajorVersion() < 3 &&
1058 !context->getExtensions().instancedArrays)
1059 {
1060 context->handleError(Error(GL_INVALID_ENUM,
1061 "GL_VERTEX_ATTRIB_ARRAY_DIVISOR requires OpenGL ES "
1062 "3.0 or GL_ANGLE_instanced_arrays."));
1063 return false;
1064 }
1065 break;
1066
1067 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
1068 if (context->getClientMajorVersion() < 3)
1069 {
1070 context->handleError(Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0."));
1071 return false;
1072 }
1073 break;
1074
1075 default:
1076 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1077 return false;
1078 }
1079 }
1080
1081 if (length)
1082 {
1083 if (pname == GL_CURRENT_VERTEX_ATTRIB)
1084 {
1085 *length = 4;
1086 }
1087 else
1088 {
1089 *length = 1;
1090 }
1091 }
1092
1093 return true;
1094}
1095
Geoff Lang6899b872016-10-14 11:30:13 -04001096bool ValidateGetActiveUniformBlockivBase(Context *context,
1097 GLuint program,
1098 GLuint uniformBlockIndex,
1099 GLenum pname,
1100 GLsizei *length)
1101{
1102 if (length)
1103 {
1104 *length = 0;
1105 }
1106
1107 if (context->getClientMajorVersion() < 3)
1108 {
1109 context->handleError(
1110 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1111 return false;
1112 }
1113
1114 Program *programObject = GetValidProgram(context, program);
1115 if (!programObject)
1116 {
1117 return false;
1118 }
1119
1120 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
1121 {
1122 context->handleError(
1123 Error(GL_INVALID_VALUE, "uniformBlockIndex exceeds active uniform block count."));
1124 return false;
1125 }
1126
1127 switch (pname)
1128 {
1129 case GL_UNIFORM_BLOCK_BINDING:
1130 case GL_UNIFORM_BLOCK_DATA_SIZE:
1131 case GL_UNIFORM_BLOCK_NAME_LENGTH:
1132 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1133 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1134 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1135 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1136 break;
1137
1138 default:
1139 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1140 return false;
1141 }
1142
1143 if (length)
1144 {
1145 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
1146 {
1147 const UniformBlock &uniformBlock =
1148 programObject->getUniformBlockByIndex(uniformBlockIndex);
1149 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
1150 }
1151 else
1152 {
1153 *length = 1;
1154 }
1155 }
1156
1157 return true;
1158}
1159
Geoff Langebebe1c2016-10-14 12:01:31 -04001160bool ValidateGetBufferParameterBase(ValidationContext *context,
1161 GLenum target,
1162 GLenum pname,
1163 bool pointerVersion,
1164 GLsizei *numParams)
1165{
1166 if (numParams)
1167 {
1168 *numParams = 0;
1169 }
1170
1171 if (!ValidBufferTarget(context, target))
1172 {
1173 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
1174 return false;
1175 }
1176
1177 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
1178 if (!buffer)
1179 {
1180 // A null buffer means that "0" is bound to the requested buffer target
1181 context->handleError(Error(GL_INVALID_OPERATION, "No buffer bound."));
1182 return false;
1183 }
1184
1185 const Extensions &extensions = context->getExtensions();
1186
1187 switch (pname)
1188 {
1189 case GL_BUFFER_USAGE:
1190 case GL_BUFFER_SIZE:
1191 break;
1192
1193 case GL_BUFFER_ACCESS_OES:
1194 if (!extensions.mapBuffer)
1195 {
1196 context->handleError(
1197 Error(GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_OES_map_buffer."));
1198 return false;
1199 }
1200 break;
1201
1202 case GL_BUFFER_MAPPED:
1203 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
1204 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
1205 !extensions.mapBufferRange)
1206 {
1207 context->handleError(Error(
1208 GL_INVALID_ENUM,
1209 "pname requires OpenGL ES 3.0, GL_OES_map_buffer or GL_EXT_map_buffer_range."));
1210 return false;
1211 }
1212 break;
1213
1214 case GL_BUFFER_MAP_POINTER:
1215 if (!pointerVersion)
1216 {
1217 context->handleError(
1218 Error(GL_INVALID_ENUM,
1219 "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv."));
1220 return false;
1221 }
1222 break;
1223
1224 case GL_BUFFER_ACCESS_FLAGS:
1225 case GL_BUFFER_MAP_OFFSET:
1226 case GL_BUFFER_MAP_LENGTH:
1227 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
1228 {
1229 context->handleError(Error(
1230 GL_INVALID_ENUM, "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range."));
1231 return false;
1232 }
1233 break;
1234
1235 default:
1236 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1237 return false;
1238 }
1239
1240 // All buffer parameter queries return one value.
1241 if (numParams)
1242 {
1243 *numParams = 1;
1244 }
1245
1246 return true;
1247}
1248
Geoff Lang0a9661f2016-10-20 10:59:20 -07001249bool ValidateGetInternalFormativBase(Context *context,
1250 GLenum target,
1251 GLenum internalformat,
1252 GLenum pname,
1253 GLsizei bufSize,
1254 GLsizei *numParams)
1255{
1256 if (numParams)
1257 {
1258 *numParams = 0;
1259 }
1260
1261 if (context->getClientMajorVersion() < 3)
1262 {
1263 context->handleError(
1264 Error(GL_INVALID_OPERATION, "Context does not support OpenGL ES 3.0."));
1265 return false;
1266 }
1267
1268 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1269 if (!formatCaps.renderable)
1270 {
1271 context->handleError(Error(GL_INVALID_ENUM, "Internal format is not renderable."));
1272 return false;
1273 }
1274
1275 switch (target)
1276 {
1277 case GL_RENDERBUFFER:
1278 break;
1279
1280 default:
1281 context->handleError(Error(GL_INVALID_ENUM, "Invalid target."));
1282 return false;
1283 }
1284
1285 if (bufSize < 0)
1286 {
1287 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
1288 return false;
1289 }
1290
1291 GLsizei maxWriteParams = 0;
1292 switch (pname)
1293 {
1294 case GL_NUM_SAMPLE_COUNTS:
1295 maxWriteParams = 1;
1296 break;
1297
1298 case GL_SAMPLES:
1299 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
1300 break;
1301
1302 default:
1303 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
1304 return false;
1305 }
1306
1307 if (numParams)
1308 {
1309 // glGetInternalFormativ will not overflow bufSize
1310 *numParams = std::min(bufSize, maxWriteParams);
1311 }
1312
1313 return true;
1314}
1315
Geoff Langf41a7152016-09-19 15:11:17 -04001316} // anonymous namespace
1317
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001318bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -04001319{
Jamie Madilld7460c72014-01-21 16:38:14 -05001320 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -04001321 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001322 case GL_TEXTURE_2D:
1323 case GL_TEXTURE_CUBE_MAP:
1324 return true;
Jamie Madill35d15012013-10-07 10:46:37 -04001325
He Yunchaoced53ae2016-11-29 15:00:51 +08001326 case GL_TEXTURE_3D:
1327 case GL_TEXTURE_2D_ARRAY:
1328 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -05001329
He Yunchaoced53ae2016-11-29 15:00:51 +08001330 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08001331 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -04001332
He Yunchaoced53ae2016-11-29 15:00:51 +08001333 default:
1334 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -05001335 }
Jamie Madill35d15012013-10-07 10:46:37 -04001336}
1337
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001338bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
1339{
1340 switch (target)
1341 {
1342 case GL_TEXTURE_2D:
1343 case GL_TEXTURE_CUBE_MAP:
1344 return true;
1345
1346 default:
1347 return false;
1348 }
1349}
1350
1351bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
1352{
1353 switch (target)
1354 {
1355 case GL_TEXTURE_3D:
1356 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +03001357 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001358
1359 default:
1360 return false;
1361 }
1362}
1363
Ian Ewellbda75592016-04-18 17:25:54 -04001364// Most texture GL calls are not compatible with external textures, so we have a separate validation
1365// function for use in the GL calls that do
1366bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
1367{
1368 return (target == GL_TEXTURE_EXTERNAL_OES) &&
1369 (context->getExtensions().eglImageExternal ||
1370 context->getExtensions().eglStreamConsumerExternal);
1371}
1372
Shannon Woods4dfed832014-03-17 20:03:39 -04001373// This function differs from ValidTextureTarget in that the target must be
1374// usable as the destination of a 2D operation-- so a cube face is valid, but
1375// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -04001376// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -05001377bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -04001378{
1379 switch (target)
1380 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001381 case GL_TEXTURE_2D:
1382 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1383 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1384 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1385 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1386 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1387 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1388 return true;
1389 default:
1390 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001391 }
1392}
1393
1394bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1395{
1396 switch (target)
1397 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001398 case GL_TEXTURE_3D:
1399 case GL_TEXTURE_2D_ARRAY:
1400 return true;
1401 default:
1402 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001403 }
1404}
1405
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001406bool ValidFramebufferTarget(GLenum target)
1407{
He Yunchaoced53ae2016-11-29 15:00:51 +08001408 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1409 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001410 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001411
1412 switch (target)
1413 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001414 case GL_FRAMEBUFFER:
1415 return true;
1416 case GL_READ_FRAMEBUFFER:
1417 return true;
1418 case GL_DRAW_FRAMEBUFFER:
1419 return true;
1420 default:
1421 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001422 }
1423}
1424
Jamie Madill29639852016-09-02 15:00:09 -04001425bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001426{
1427 switch (target)
1428 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001429 case GL_ARRAY_BUFFER:
1430 case GL_ELEMENT_ARRAY_BUFFER:
1431 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001432
He Yunchaoced53ae2016-11-29 15:00:51 +08001433 case GL_PIXEL_PACK_BUFFER:
1434 case GL_PIXEL_UNPACK_BUFFER:
1435 return (context->getExtensions().pixelBufferObject ||
1436 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001437
He Yunchaoced53ae2016-11-29 15:00:51 +08001438 case GL_COPY_READ_BUFFER:
1439 case GL_COPY_WRITE_BUFFER:
1440 case GL_TRANSFORM_FEEDBACK_BUFFER:
1441 case GL_UNIFORM_BUFFER:
1442 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001443
He Yunchaoced53ae2016-11-29 15:00:51 +08001444 case GL_ATOMIC_COUNTER_BUFFER:
1445 case GL_SHADER_STORAGE_BUFFER:
1446 case GL_DRAW_INDIRECT_BUFFER:
1447 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001448 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001449
He Yunchaoced53ae2016-11-29 15:00:51 +08001450 default:
1451 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001452 }
1453}
1454
Jamie Madillc29968b2016-01-20 11:17:23 -05001455bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001456{
Jamie Madillc29968b2016-01-20 11:17:23 -05001457 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001458 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001459 switch (target)
1460 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001461 case GL_TEXTURE_2D:
1462 maxDimension = caps.max2DTextureSize;
1463 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001464 case GL_TEXTURE_CUBE_MAP:
1465 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1466 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1467 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1468 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1469 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1470 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1471 maxDimension = caps.maxCubeMapTextureSize;
1472 break;
1473 case GL_TEXTURE_3D:
1474 maxDimension = caps.max3DTextureSize;
1475 break;
1476 case GL_TEXTURE_2D_ARRAY:
1477 maxDimension = caps.max2DTextureSize;
1478 break;
1479 default:
1480 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001481 }
1482
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001483 return level <= gl::log2(static_cast<int>(maxDimension));
Geoff Langce635692013-09-24 13:56:32 -04001484}
1485
Austin Kinross08528e12015-10-07 16:24:40 -07001486bool ValidImageSizeParameters(const Context *context,
1487 GLenum target,
1488 GLint level,
1489 GLsizei width,
1490 GLsizei height,
1491 GLsizei depth,
1492 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001493{
1494 if (level < 0 || width < 0 || height < 0 || depth < 0)
1495 {
1496 return false;
1497 }
1498
Austin Kinross08528e12015-10-07 16:24:40 -07001499 // TexSubImage parameters can be NPOT without textureNPOT extension,
1500 // as long as the destination texture is POT.
1501 if (!isSubImage && !context->getExtensions().textureNPOT &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001502 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001503 {
1504 return false;
1505 }
1506
1507 if (!ValidMipLevel(context, target, level))
1508 {
1509 return false;
1510 }
1511
1512 return true;
1513}
1514
Geoff Lang0d8b7242015-09-09 14:56:53 -04001515bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1516{
1517 // List of compressed format that require that the texture size is smaller than or a multiple of
1518 // the compressed block size.
1519 switch (internalFormat)
1520 {
1521 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1522 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1523 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1524 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Minmin Gonge3939b92015-12-01 15:36:51 -08001525 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001526 return true;
1527
1528 default:
1529 return false;
1530 }
1531}
1532
Jamie Madillc29968b2016-01-20 11:17:23 -05001533bool ValidCompressedImageSize(const ValidationContext *context,
1534 GLenum internalFormat,
1535 GLsizei width,
1536 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001537{
Geoff Lang5d601382014-07-22 15:14:06 -04001538 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
1539 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001540 {
1541 return false;
1542 }
1543
Geoff Lang0d8b7242015-09-09 14:56:53 -04001544 if (width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001545 {
1546 return false;
1547 }
1548
Geoff Lang0d8b7242015-09-09 14:56:53 -04001549 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1550 {
1551 if ((static_cast<GLuint>(width) > formatInfo.compressedBlockWidth &&
1552 width % formatInfo.compressedBlockWidth != 0) ||
1553 (static_cast<GLuint>(height) > formatInfo.compressedBlockHeight &&
1554 height % formatInfo.compressedBlockHeight != 0))
1555 {
1556 return false;
1557 }
1558 }
1559
Geoff Langd4f180b2013-09-24 13:57:44 -04001560 return true;
1561}
1562
Geoff Langff5b2d52016-09-07 11:32:23 -04001563bool ValidImageDataSize(ValidationContext *context,
1564 GLenum textureTarget,
1565 GLsizei width,
1566 GLsizei height,
1567 GLsizei depth,
1568 GLenum internalFormat,
1569 GLenum type,
1570 const GLvoid *pixels,
1571 GLsizei imageSize)
1572{
1573 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1574 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1575 {
1576 // Checks are not required
1577 return true;
1578 }
1579
1580 // ...the data would be unpacked from the buffer object such that the memory reads required
1581 // would exceed the data store size.
1582 GLenum sizedFormat = GetSizedInternalFormat(internalFormat, type);
1583 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
1584 const gl::Extents size(width, height, depth);
1585 const auto &unpack = context->getGLState().getUnpackState();
1586
1587 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1588 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1589 if (endByteOrErr.isError())
1590 {
1591 context->handleError(endByteOrErr.getError());
1592 return false;
1593 }
1594
1595 GLuint endByte = endByteOrErr.getResult();
1596
1597 if (pixelUnpackBuffer)
1598 {
1599 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1600 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1601 checkedEndByte += checkedOffset;
1602
1603 if (!checkedEndByte.IsValid() ||
1604 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1605 {
1606 // Overflow past the end of the buffer
1607 context->handleError(Error(GL_INVALID_OPERATION));
1608 return false;
1609 }
1610 }
1611 else
1612 {
1613 ASSERT(imageSize >= 0);
1614 if (pixels == nullptr && imageSize != 0)
1615 {
1616 context->handleError(
1617 Error(GL_INVALID_OPERATION, "imageSize must be 0 if no texture data is provided."));
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001618 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001619 }
1620
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001621 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001622 {
1623 context->handleError(
1624 Error(GL_INVALID_OPERATION, "imageSize must be at least %u.", endByte));
1625 return false;
1626 }
1627 }
1628
1629 return true;
1630}
1631
Geoff Lang37dde692014-01-31 16:34:54 -05001632bool ValidQueryType(const Context *context, GLenum queryType)
1633{
He Yunchaoced53ae2016-11-29 15:00:51 +08001634 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1635 "GL extension enums not equal.");
1636 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1637 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001638
1639 switch (queryType)
1640 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001641 case GL_ANY_SAMPLES_PASSED:
1642 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1643 return true;
1644 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1645 return (context->getClientMajorVersion() >= 3);
1646 case GL_TIME_ELAPSED_EXT:
1647 return context->getExtensions().disjointTimerQuery;
1648 case GL_COMMANDS_COMPLETED_CHROMIUM:
1649 return context->getExtensions().syncQuery;
1650 default:
1651 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001652 }
1653}
1654
Jamie Madillef300b12016-10-07 15:12:09 -04001655Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001656{
He Yunchaoced53ae2016-11-29 15:00:51 +08001657 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1658 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1659 // or program object and INVALID_OPERATION if the provided name identifies an object
1660 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001661
Dian Xiang769769a2015-09-09 15:20:08 -07001662 Program *validProgram = context->getProgram(id);
1663
1664 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001665 {
Dian Xiang769769a2015-09-09 15:20:08 -07001666 if (context->getShader(id))
1667 {
Jamie Madill437fa652016-05-03 15:13:24 -04001668 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001669 Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name"));
1670 }
1671 else
1672 {
Jamie Madill437fa652016-05-03 15:13:24 -04001673 context->handleError(Error(GL_INVALID_VALUE, "Program name is not valid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001674 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001675 }
Dian Xiang769769a2015-09-09 15:20:08 -07001676
1677 return validProgram;
1678}
1679
Jamie Madillef300b12016-10-07 15:12:09 -04001680Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001681{
1682 // See ValidProgram for spec details.
1683
1684 Shader *validShader = context->getShader(id);
1685
1686 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001687 {
Dian Xiang769769a2015-09-09 15:20:08 -07001688 if (context->getProgram(id))
1689 {
Jamie Madill437fa652016-05-03 15:13:24 -04001690 context->handleError(
Dian Xiang769769a2015-09-09 15:20:08 -07001691 Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name"));
1692 }
1693 else
1694 {
Jamie Madill437fa652016-05-03 15:13:24 -04001695 context->handleError(Error(GL_INVALID_VALUE, "Shader name is invalid"));
Dian Xiang769769a2015-09-09 15:20:08 -07001696 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001697 }
Dian Xiang769769a2015-09-09 15:20:08 -07001698
1699 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001700}
1701
Geoff Langb1196682014-07-23 13:47:29 -04001702bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001703{
1704 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1705 {
1706 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1707
Geoff Langaae65a42014-05-26 12:43:44 -04001708 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001709 {
Jamie Madill437fa652016-05-03 15:13:24 -04001710 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001711 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001712 }
1713 }
1714 else
1715 {
1716 switch (attachment)
1717 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001718 case GL_DEPTH_ATTACHMENT:
1719 case GL_STENCIL_ATTACHMENT:
1720 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001721
He Yunchaoced53ae2016-11-29 15:00:51 +08001722 case GL_DEPTH_STENCIL_ATTACHMENT:
1723 if (!context->getExtensions().webglCompatibility &&
1724 context->getClientMajorVersion() < 3)
1725 {
1726 context->handleError(Error(GL_INVALID_ENUM));
1727 return false;
1728 }
1729 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001730
He Yunchaoced53ae2016-11-29 15:00:51 +08001731 default:
1732 context->handleError(Error(GL_INVALID_ENUM));
1733 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001734 }
1735 }
1736
1737 return true;
1738}
1739
He Yunchaoced53ae2016-11-29 15:00:51 +08001740bool ValidateRenderbufferStorageParametersBase(gl::Context *context,
1741 GLenum target,
1742 GLsizei samples,
1743 GLenum internalformat,
1744 GLsizei width,
1745 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001746{
1747 switch (target)
1748 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001749 case GL_RENDERBUFFER:
1750 break;
1751 default:
1752 context->handleError(Error(GL_INVALID_ENUM));
1753 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001754 }
1755
1756 if (width < 0 || height < 0 || samples < 0)
1757 {
Jamie Madill437fa652016-05-03 15:13:24 -04001758 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001759 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001760 }
1761
Geoff Langd87878e2014-09-19 15:42:59 -04001762 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1763 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001764 {
Jamie Madill437fa652016-05-03 15:13:24 -04001765 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001766 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001767 }
1768
1769 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1770 // 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 -08001771 // only sized internal formats.
Geoff Langd87878e2014-09-19 15:42:59 -04001772 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -04001773 if (formatInfo.pixelBytes == 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001774 {
Jamie Madill437fa652016-05-03 15:13:24 -04001775 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001776 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001777 }
1778
Geoff Langaae65a42014-05-26 12:43:44 -04001779 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001780 {
Jamie Madill437fa652016-05-03 15:13:24 -04001781 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001782 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001783 }
1784
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001785 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001786 if (handle == 0)
1787 {
Jamie Madill437fa652016-05-03 15:13:24 -04001788 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001789 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001790 }
1791
1792 return true;
1793}
1794
He Yunchaoced53ae2016-11-29 15:00:51 +08001795bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context,
1796 GLenum target,
1797 GLsizei samples,
1798 GLenum internalformat,
1799 GLsizei width,
1800 GLsizei height)
Corentin Walleze0902642014-11-04 12:32:15 -08001801{
Austin Kinrossd2cf3ad2015-01-07 14:00:30 -08001802 ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
Corentin Walleze0902642014-11-04 12:32:15 -08001803
1804 // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
Geoff Langdef624b2015-04-13 10:46:56 -04001805 // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
Corentin Walleze0902642014-11-04 12:32:15 -08001806 // generated.
Geoff Langdef624b2015-04-13 10:46:56 -04001807 if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
Corentin Walleze0902642014-11-04 12:32:15 -08001808 {
Jamie Madill437fa652016-05-03 15:13:24 -04001809 context->handleError(Error(GL_INVALID_VALUE));
Corentin Walleze0902642014-11-04 12:32:15 -08001810 return false;
1811 }
1812
1813 // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
1814 // the specified storage. This is different than ES 3.0 in which a sample number higher
1815 // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
Geoff Langa4903b72015-03-02 16:02:48 -08001816 // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001817 if (context->getClientMajorVersion() >= 3)
Corentin Walleze0902642014-11-04 12:32:15 -08001818 {
Geoff Langa4903b72015-03-02 16:02:48 -08001819 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
1820 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
1821 {
Jamie Madill437fa652016-05-03 15:13:24 -04001822 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langa4903b72015-03-02 16:02:48 -08001823 return false;
1824 }
Corentin Walleze0902642014-11-04 12:32:15 -08001825 }
1826
He Yunchaoced53ae2016-11-29 15:00:51 +08001827 return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
1828 width, height);
Corentin Walleze0902642014-11-04 12:32:15 -08001829}
1830
He Yunchaoced53ae2016-11-29 15:00:51 +08001831bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1832 GLenum target,
1833 GLenum attachment,
1834 GLenum renderbuffertarget,
1835 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001836{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001837 if (!ValidFramebufferTarget(target))
1838 {
Jamie Madill437fa652016-05-03 15:13:24 -04001839 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04001840 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001841 }
1842
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001843 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001844
Jamie Madill84115c92015-04-23 15:00:07 -04001845 ASSERT(framebuffer);
1846 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001847 {
Jamie Madill437fa652016-05-03 15:13:24 -04001848 context->handleError(
1849 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04001850 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001851 }
1852
Jamie Madillb4472272014-07-03 10:38:55 -04001853 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001854 {
Jamie Madillb4472272014-07-03 10:38:55 -04001855 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001856 }
1857
Jamie Madillab9d82c2014-01-21 16:38:14 -05001858 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1859 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1860 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1861 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1862 if (renderbuffer != 0)
1863 {
1864 if (!context->getRenderbuffer(renderbuffer))
1865 {
Jamie Madill437fa652016-05-03 15:13:24 -04001866 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001867 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001868 }
1869 }
1870
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001871 return true;
1872}
1873
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001874bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001875 GLint srcX0,
1876 GLint srcY0,
1877 GLint srcX1,
1878 GLint srcY1,
1879 GLint dstX0,
1880 GLint dstY0,
1881 GLint dstX1,
1882 GLint dstY1,
1883 GLbitfield mask,
1884 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001885{
1886 switch (filter)
1887 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001888 case GL_NEAREST:
1889 break;
1890 case GL_LINEAR:
1891 break;
1892 default:
1893 context->handleError(Error(GL_INVALID_ENUM));
1894 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001895 }
1896
1897 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1898 {
Jamie Madill437fa652016-05-03 15:13:24 -04001899 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04001900 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001901 }
1902
1903 if (mask == 0)
1904 {
1905 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1906 // buffers are copied.
1907 return false;
1908 }
1909
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001910 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1911 // color buffer, leaving only nearest being unfiltered from above
1912 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1913 {
Jamie Madill437fa652016-05-03 15:13:24 -04001914 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001915 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001916 }
1917
Jamie Madill51f40ec2016-06-15 14:06:00 -04001918 const auto &glState = context->getGLState();
1919 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1920 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001921
1922 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001923 {
Jamie Madill437fa652016-05-03 15:13:24 -04001924 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001925 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001926 }
1927
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001928 if (readFramebuffer->id() == drawFramebuffer->id())
1929 {
1930 context->handleError(Error(GL_INVALID_OPERATION));
1931 return false;
1932 }
1933
Jamie Madill51f40ec2016-06-15 14:06:00 -04001934 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001935 {
Jamie Madill437fa652016-05-03 15:13:24 -04001936 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001937 return false;
1938 }
1939
Jamie Madill51f40ec2016-06-15 14:06:00 -04001940 if (drawFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001941 {
Jamie Madill437fa652016-05-03 15:13:24 -04001942 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Jamie Madill48faf802014-11-06 15:27:22 -05001943 return false;
1944 }
1945
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001946 if (drawFramebuffer->getSamples(context->getContextState()) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001947 {
Jamie Madill437fa652016-05-03 15:13:24 -04001948 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04001949 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001950 }
1951
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001952 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1953
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001954 if (mask & GL_COLOR_BUFFER_BIT)
1955 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001956 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
1957 const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001958 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001959
1960 if (readColorBuffer && drawColorBuffer)
1961 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001962 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001963
Geoff Langa15472a2015-08-11 11:48:03 -04001964 for (size_t drawbufferIdx = 0;
1965 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001966 {
Geoff Langa15472a2015-08-11 11:48:03 -04001967 const FramebufferAttachment *attachment =
1968 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1969 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001970 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001971 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001972
Geoff Langb2f3d052013-08-13 12:49:27 -04001973 // The GL ES 3.0.2 spec (pg 193) states that:
1974 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001975 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1976 // as well
1977 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1978 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001979 // Changes with EXT_color_buffer_float:
1980 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001981 GLenum readComponentType = readFormat.info->componentType;
1982 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001983 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001984 readComponentType == GL_SIGNED_NORMALIZED);
1985 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1986 drawComponentType == GL_SIGNED_NORMALIZED);
1987
1988 if (extensions.colorBufferFloat)
1989 {
1990 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1991 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1992
1993 if (readFixedOrFloat != drawFixedOrFloat)
1994 {
Jamie Madill437fa652016-05-03 15:13:24 -04001995 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05001996 "If the read buffer contains fixed-point or "
1997 "floating-point values, the draw buffer "
1998 "must as well."));
1999 return false;
2000 }
2001 }
2002 else if (readFixedPoint != drawFixedPoint)
2003 {
Jamie Madill437fa652016-05-03 15:13:24 -04002004 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madill6163c752015-12-07 16:32:59 -05002005 "If the read buffer contains fixed-point "
2006 "values, the draw buffer must as well."));
2007 return false;
2008 }
2009
2010 if (readComponentType == GL_UNSIGNED_INT &&
2011 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002012 {
Jamie Madill437fa652016-05-03 15:13:24 -04002013 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002014 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002015 }
2016
Jamie Madill6163c752015-12-07 16:32:59 -05002017 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002018 {
Jamie Madill437fa652016-05-03 15:13:24 -04002019 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002020 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002021 }
2022
Jamie Madilla3944d42016-07-22 22:13:26 -04002023 if (readColorBuffer->getSamples() > 0 &&
2024 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
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 }
2030 }
2031
Jamie Madilla3944d42016-07-22 22:13:26 -04002032 if ((readFormat.info->componentType == GL_INT ||
2033 readFormat.info->componentType == GL_UNSIGNED_INT) &&
2034 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002035 {
Jamie Madill437fa652016-05-03 15:13:24 -04002036 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002037 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002038 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002039 }
2040 }
2041
He Yunchaoced53ae2016-11-29 15:00:51 +08002042 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002043 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
2044 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002045 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002046 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002047 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002048 const gl::FramebufferAttachment *readBuffer =
2049 readFramebuffer->getAttachment(attachments[i]);
2050 const gl::FramebufferAttachment *drawBuffer =
2051 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002052
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002053 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002054 {
Jamie Madilla3944d42016-07-22 22:13:26 -04002055 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002056 {
Jamie Madill437fa652016-05-03 15:13:24 -04002057 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002058 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002059 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002060
Dongseong Hwang44b422c2014-12-09 15:42:01 +02002061 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002062 {
Jamie Madill437fa652016-05-03 15:13:24 -04002063 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002064 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04002065 }
2066 }
2067 }
2068 }
2069
2070 return true;
2071}
2072
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002073bool ValidateReadPixels(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05002074 GLint x,
2075 GLint y,
2076 GLsizei width,
2077 GLsizei height,
2078 GLenum format,
2079 GLenum type,
2080 GLvoid *pixels)
Jamie Madill26e91952014-03-05 15:01:27 -05002081{
Geoff Lang62fce5b2016-09-30 10:46:35 -04002082 return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, pixels);
2083}
2084
2085bool ValidateReadPixelsRobustANGLE(ValidationContext *context,
2086 GLint x,
2087 GLint y,
2088 GLsizei width,
2089 GLsizei height,
2090 GLenum format,
2091 GLenum type,
2092 GLsizei bufSize,
2093 GLsizei *length,
2094 GLvoid *pixels)
2095{
2096 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05002097 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002098 return false;
2099 }
2100
Geoff Lang62fce5b2016-09-30 10:46:35 -04002101 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
2102 pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05002103 {
Geoff Langb1196682014-07-23 13:47:29 -04002104 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002105 }
2106
Geoff Lang62fce5b2016-09-30 10:46:35 -04002107 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05002108 {
Geoff Langb1196682014-07-23 13:47:29 -04002109 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002110 }
2111
Jamie Madillc29968b2016-01-20 11:17:23 -05002112 return true;
2113}
2114
2115bool ValidateReadnPixelsEXT(Context *context,
2116 GLint x,
2117 GLint y,
2118 GLsizei width,
2119 GLsizei height,
2120 GLenum format,
2121 GLenum type,
2122 GLsizei bufSize,
2123 GLvoid *pixels)
2124{
2125 if (bufSize < 0)
2126 {
Jamie Madill437fa652016-05-03 15:13:24 -04002127 context->handleError(Error(GL_INVALID_VALUE, "bufSize must be a positive number"));
Jamie Madillc29968b2016-01-20 11:17:23 -05002128 return false;
2129 }
2130
Geoff Lang62fce5b2016-09-30 10:46:35 -04002131 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
2132 pixels);
2133}
Jamie Madill26e91952014-03-05 15:01:27 -05002134
Geoff Lang62fce5b2016-09-30 10:46:35 -04002135bool ValidateReadnPixelsRobustANGLE(ValidationContext *context,
2136 GLint x,
2137 GLint y,
2138 GLsizei width,
2139 GLsizei height,
2140 GLenum format,
2141 GLenum type,
2142 GLsizei bufSize,
2143 GLsizei *length,
2144 GLvoid *data)
2145{
2146 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002147 {
Jamie Madille2e406c2016-06-02 13:04:10 -04002148 return false;
2149 }
2150
Geoff Lang62fce5b2016-09-30 10:46:35 -04002151 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04002152 {
Jamie Madillc29968b2016-01-20 11:17:23 -05002153 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05002154 }
2155
Geoff Lang62fce5b2016-09-30 10:46:35 -04002156 if (!ValidateRobustBufferSize(context, bufSize, *length))
2157 {
2158 return false;
2159 }
2160
2161 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05002162}
2163
Olli Etuaho41997e72016-03-10 13:38:39 +02002164bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002165{
2166 if (!context->getExtensions().occlusionQueryBoolean &&
2167 !context->getExtensions().disjointTimerQuery)
2168 {
Jamie Madill437fa652016-05-03 15:13:24 -04002169 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002170 return false;
2171 }
2172
Olli Etuaho41997e72016-03-10 13:38:39 +02002173 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002174}
2175
Olli Etuaho41997e72016-03-10 13:38:39 +02002176bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002177{
2178 if (!context->getExtensions().occlusionQueryBoolean &&
2179 !context->getExtensions().disjointTimerQuery)
2180 {
Jamie Madill437fa652016-05-03 15:13:24 -04002181 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002182 return false;
2183 }
2184
Olli Etuaho41997e72016-03-10 13:38:39 +02002185 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002186}
2187
2188bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002189{
2190 if (!ValidQueryType(context, target))
2191 {
Jamie Madill437fa652016-05-03 15:13:24 -04002192 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002193 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002194 }
2195
2196 if (id == 0)
2197 {
Jamie Madill437fa652016-05-03 15:13:24 -04002198 context->handleError(Error(GL_INVALID_OPERATION, "Query id is 0"));
Geoff Langb1196682014-07-23 13:47:29 -04002199 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002200 }
2201
2202 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
2203 // of zero, if the active query object name for <target> is non-zero (for the
2204 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
2205 // the active query for either target is non-zero), if <id> is the name of an
2206 // existing query object whose type does not match <target>, or if <id> is the
2207 // active query object name for any query type, the error INVALID_OPERATION is
2208 // generated.
2209
2210 // Ensure no other queries are active
2211 // NOTE: If other queries than occlusion are supported, we will need to check
2212 // separately that:
2213 // a) The query ID passed is not the current active query for any target/type
2214 // b) There are no active queries for the requested target (and in the case
2215 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
2216 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002217
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002218 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002219 {
Jamie Madill437fa652016-05-03 15:13:24 -04002220 context->handleError(Error(GL_INVALID_OPERATION, "Other query is active"));
Geoff Langb1196682014-07-23 13:47:29 -04002221 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002222 }
2223
2224 Query *queryObject = context->getQuery(id, true, target);
2225
2226 // check that name was obtained with glGenQueries
2227 if (!queryObject)
2228 {
Jamie Madill437fa652016-05-03 15:13:24 -04002229 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Geoff Langb1196682014-07-23 13:47:29 -04002230 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002231 }
2232
2233 // check for type mismatch
2234 if (queryObject->getType() != target)
2235 {
Jamie Madill437fa652016-05-03 15:13:24 -04002236 context->handleError(Error(GL_INVALID_OPERATION, "Query type does not match target"));
Geoff Langb1196682014-07-23 13:47:29 -04002237 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002238 }
2239
2240 return true;
2241}
2242
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002243bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2244{
2245 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002246 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002247 {
Jamie Madill437fa652016-05-03 15:13:24 -04002248 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002249 return false;
2250 }
2251
2252 return ValidateBeginQueryBase(context, target, id);
2253}
2254
2255bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002256{
2257 if (!ValidQueryType(context, target))
2258 {
Jamie Madill437fa652016-05-03 15:13:24 -04002259 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Geoff Langb1196682014-07-23 13:47:29 -04002260 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002261 }
2262
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002263 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002264
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002265 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002266 {
Jamie Madill437fa652016-05-03 15:13:24 -04002267 context->handleError(Error(GL_INVALID_OPERATION, "Query target not active"));
Geoff Langb1196682014-07-23 13:47:29 -04002268 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002269 }
2270
Jamie Madill45c785d2014-05-13 14:09:34 -04002271 return true;
2272}
2273
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002274bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2275{
2276 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002277 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002278 {
Jamie Madill437fa652016-05-03 15:13:24 -04002279 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002280 return false;
2281 }
2282
2283 return ValidateEndQueryBase(context, target);
2284}
2285
2286bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2287{
2288 if (!context->getExtensions().disjointTimerQuery)
2289 {
Jamie Madill437fa652016-05-03 15:13:24 -04002290 context->handleError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002291 return false;
2292 }
2293
2294 if (target != GL_TIMESTAMP_EXT)
2295 {
Jamie Madill437fa652016-05-03 15:13:24 -04002296 context->handleError(Error(GL_INVALID_ENUM, "Invalid query target"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002297 return false;
2298 }
2299
2300 Query *queryObject = context->getQuery(id, true, target);
2301 if (queryObject == nullptr)
2302 {
Jamie Madill437fa652016-05-03 15:13:24 -04002303 context->handleError(Error(GL_INVALID_OPERATION, "Invalid query id"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002304 return false;
2305 }
2306
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002307 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002308 {
Jamie Madill437fa652016-05-03 15:13:24 -04002309 context->handleError(Error(GL_INVALID_OPERATION, "Query is active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002310 return false;
2311 }
2312
2313 return true;
2314}
2315
Geoff Lang2186c382016-10-14 10:54:54 -04002316bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002317{
Geoff Lang2186c382016-10-14 10:54:54 -04002318 if (numParams)
2319 {
2320 *numParams = 0;
2321 }
2322
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002323 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2324 {
Jamie Madill437fa652016-05-03 15:13:24 -04002325 context->handleError(Error(GL_INVALID_ENUM, "Invalid query type"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002326 return false;
2327 }
2328
2329 switch (pname)
2330 {
2331 case GL_CURRENT_QUERY_EXT:
2332 if (target == GL_TIMESTAMP_EXT)
2333 {
Jamie Madill437fa652016-05-03 15:13:24 -04002334 context->handleError(
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002335 Error(GL_INVALID_ENUM, "Cannot use current query for timestamp"));
2336 return false;
2337 }
2338 break;
2339 case GL_QUERY_COUNTER_BITS_EXT:
2340 if (!context->getExtensions().disjointTimerQuery ||
2341 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2342 {
Jamie Madill437fa652016-05-03 15:13:24 -04002343 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002344 return false;
2345 }
2346 break;
2347 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002348 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002349 return false;
2350 }
2351
Geoff Lang2186c382016-10-14 10:54:54 -04002352 if (numParams)
2353 {
2354 // All queries return only one value
2355 *numParams = 1;
2356 }
2357
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002358 return true;
2359}
2360
2361bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2362{
2363 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002364 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002365 {
Jamie Madill437fa652016-05-03 15:13:24 -04002366 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002367 return false;
2368 }
2369
Geoff Lang2186c382016-10-14 10:54:54 -04002370 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002371}
2372
Geoff Lang2186c382016-10-14 10:54:54 -04002373bool ValidateGetQueryivRobustANGLE(Context *context,
2374 GLenum target,
2375 GLenum pname,
2376 GLsizei bufSize,
2377 GLsizei *length,
2378 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002379{
Geoff Lang2186c382016-10-14 10:54:54 -04002380 if (!ValidateRobustEntryPoint(context, bufSize))
2381 {
2382 return false;
2383 }
2384
2385 if (!ValidateGetQueryivBase(context, target, pname, length))
2386 {
2387 return false;
2388 }
2389
2390 if (!ValidateRobustBufferSize(context, bufSize, *length))
2391 {
2392 return false;
2393 }
2394
2395 return true;
2396}
2397
2398bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2399{
2400 if (numParams)
2401 {
2402 *numParams = 0;
2403 }
2404
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002405 Query *queryObject = context->getQuery(id, false, GL_NONE);
2406
2407 if (!queryObject)
2408 {
Jamie Madill437fa652016-05-03 15:13:24 -04002409 context->handleError(Error(GL_INVALID_OPERATION, "Query does not exist"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002410 return false;
2411 }
2412
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002413 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002414 {
Jamie Madill437fa652016-05-03 15:13:24 -04002415 context->handleError(Error(GL_INVALID_OPERATION, "Query currently active"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002416 return false;
2417 }
2418
2419 switch (pname)
2420 {
2421 case GL_QUERY_RESULT_EXT:
2422 case GL_QUERY_RESULT_AVAILABLE_EXT:
2423 break;
2424
2425 default:
Jamie Madill437fa652016-05-03 15:13:24 -04002426 context->handleError(Error(GL_INVALID_ENUM, "Invalid pname enum"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002427 return false;
2428 }
2429
Geoff Lang2186c382016-10-14 10:54:54 -04002430 if (numParams)
2431 {
2432 *numParams = 1;
2433 }
2434
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002435 return true;
2436}
2437
2438bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2439{
2440 if (!context->getExtensions().disjointTimerQuery)
2441 {
Jamie Madill437fa652016-05-03 15:13:24 -04002442 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002443 return false;
2444 }
Geoff Lang2186c382016-10-14 10:54:54 -04002445 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2446}
2447
2448bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2449 GLuint id,
2450 GLenum pname,
2451 GLsizei bufSize,
2452 GLsizei *length,
2453 GLint *params)
2454{
2455 if (!context->getExtensions().disjointTimerQuery)
2456 {
2457 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2458 return false;
2459 }
2460
2461 if (!ValidateRobustEntryPoint(context, bufSize))
2462 {
2463 return false;
2464 }
2465
2466 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2467 {
2468 return false;
2469 }
2470
2471 if (!ValidateRobustBufferSize(context, bufSize, *length))
2472 {
2473 return false;
2474 }
2475
2476 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002477}
2478
2479bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2480{
2481 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002482 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002483 {
Jamie Madill437fa652016-05-03 15:13:24 -04002484 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002485 return false;
2486 }
Geoff Lang2186c382016-10-14 10:54:54 -04002487 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2488}
2489
2490bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2491 GLuint id,
2492 GLenum pname,
2493 GLsizei bufSize,
2494 GLsizei *length,
2495 GLuint *params)
2496{
2497 if (!context->getExtensions().disjointTimerQuery &&
2498 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2499 {
2500 context->handleError(Error(GL_INVALID_OPERATION, "Query extension not enabled"));
2501 return false;
2502 }
2503
2504 if (!ValidateRobustEntryPoint(context, bufSize))
2505 {
2506 return false;
2507 }
2508
2509 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2510 {
2511 return false;
2512 }
2513
2514 if (!ValidateRobustBufferSize(context, bufSize, *length))
2515 {
2516 return false;
2517 }
2518
2519 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002520}
2521
2522bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2523{
2524 if (!context->getExtensions().disjointTimerQuery)
2525 {
Jamie Madill437fa652016-05-03 15:13:24 -04002526 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002527 return false;
2528 }
Geoff Lang2186c382016-10-14 10:54:54 -04002529 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2530}
2531
2532bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2533 GLuint id,
2534 GLenum pname,
2535 GLsizei bufSize,
2536 GLsizei *length,
2537 GLint64 *params)
2538{
2539 if (!context->getExtensions().disjointTimerQuery)
2540 {
2541 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2542 return false;
2543 }
2544
2545 if (!ValidateRobustEntryPoint(context, bufSize))
2546 {
2547 return false;
2548 }
2549
2550 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2551 {
2552 return false;
2553 }
2554
2555 if (!ValidateRobustBufferSize(context, bufSize, *length))
2556 {
2557 return false;
2558 }
2559
2560 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002561}
2562
2563bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2564{
2565 if (!context->getExtensions().disjointTimerQuery)
2566 {
Jamie Madill437fa652016-05-03 15:13:24 -04002567 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002568 return false;
2569 }
Geoff Lang2186c382016-10-14 10:54:54 -04002570 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2571}
2572
2573bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2574 GLuint id,
2575 GLenum pname,
2576 GLsizei bufSize,
2577 GLsizei *length,
2578 GLuint64 *params)
2579{
2580 if (!context->getExtensions().disjointTimerQuery)
2581 {
2582 context->handleError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled"));
2583 return false;
2584 }
2585
2586 if (!ValidateRobustEntryPoint(context, bufSize))
2587 {
2588 return false;
2589 }
2590
2591 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2592 {
2593 return false;
2594 }
2595
2596 if (!ValidateRobustBufferSize(context, bufSize, *length))
2597 {
2598 return false;
2599 }
2600
2601 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002602}
2603
Jamie Madill62d31cb2015-09-11 13:25:51 -04002604static bool ValidateUniformCommonBase(gl::Context *context,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002605 gl::Program *program,
Jamie Madill62d31cb2015-09-11 13:25:51 -04002606 GLenum targetUniformType,
2607 GLint location,
2608 GLsizei count,
2609 const LinkedUniform **uniformOut)
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002610{
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002611 // TODO(Jiajia): Add image uniform check in future.
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002612 if (count < 0)
2613 {
Jamie Madill437fa652016-05-03 15:13:24 -04002614 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002615 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002616 }
2617
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002618 if (!program || !program->isLinked())
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002619 {
Jamie Madill437fa652016-05-03 15:13:24 -04002620 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002621 return false;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002622 }
2623
Geoff Langd8605522016-04-13 10:19:12 -04002624 if (program->isIgnoredUniformLocation(location))
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002625 {
2626 // Silently ignore the uniform command
2627 return false;
2628 }
2629
Geoff Lang7dd2e102014-11-10 15:19:26 -05002630 if (!program->isValidUniformLocation(location))
Jamie Madill36398922014-05-20 14:51:53 -04002631 {
Jamie Madill437fa652016-05-03 15:13:24 -04002632 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002633 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002634 }
2635
Jamie Madill62d31cb2015-09-11 13:25:51 -04002636 const LinkedUniform &uniform = program->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04002637
2638 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill62d31cb2015-09-11 13:25:51 -04002639 if (!uniform.isArray() && count > 1)
Jamie Madill36398922014-05-20 14:51:53 -04002640 {
Jamie Madill437fa652016-05-03 15:13:24 -04002641 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002642 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002643 }
2644
Jamie Madill62d31cb2015-09-11 13:25:51 -04002645 *uniformOut = &uniform;
Jamie Madilld7c7bb22014-05-20 10:55:54 -04002646 return true;
2647}
2648
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002649bool ValidateProgramUniform(gl::Context *context,
2650 GLenum uniformType,
2651 GLuint program,
2652 GLint location,
2653 GLsizei count)
2654{
2655 // Check for ES31 program uniform entry points
2656 if (context->getClientVersion() < Version(3, 1))
2657 {
2658 context->handleError(Error(GL_INVALID_OPERATION));
2659 return false;
2660 }
2661
2662 const LinkedUniform *uniform = nullptr;
2663 gl::Program *programObject = GetValidProgram(context, program);
2664 if (!ValidateUniformCommonBase(context, programObject, uniformType, location, count, &uniform))
2665 {
2666 return false;
2667 }
2668
2669 GLenum targetBoolType = VariableBoolVectorType(uniformType);
2670 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
2671 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2672 {
2673 context->handleError(Error(GL_INVALID_OPERATION));
2674 return false;
2675 }
2676
2677 return true;
2678}
2679
2680bool ValidateProgramUniformMatrix(gl::Context *context,
2681 GLenum matrixType,
2682 GLuint program,
2683 GLint location,
2684 GLsizei count,
2685 GLboolean transpose)
2686{
2687 // Check for ES31 program uniform entry points
2688 if (context->getClientVersion() < Version(3, 1))
2689 {
2690 context->handleError(Error(GL_INVALID_OPERATION));
2691 return false;
2692 }
2693
2694 const LinkedUniform *uniform = nullptr;
2695 gl::Program *programObject = GetValidProgram(context, program);
2696 if (!ValidateUniformCommonBase(context, programObject, matrixType, location, count, &uniform))
2697 {
2698 return false;
2699 }
2700
2701 if (uniform->type != matrixType)
2702 {
2703 context->handleError(Error(GL_INVALID_OPERATION));
2704 return false;
2705 }
2706
2707 return true;
2708}
2709
Jamie Madillaa981bd2014-05-20 10:55:55 -04002710bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count)
2711{
2712 // Check for ES3 uniform entry points
Martin Radev1be913c2016-07-11 17:59:16 +03002713 if (VariableComponentType(uniformType) == GL_UNSIGNED_INT &&
2714 context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002715 {
Jamie Madill437fa652016-05-03 15:13:24 -04002716 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002717 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002718 }
2719
Jamie Madill62d31cb2015-09-11 13:25:51 -04002720 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002721 gl::Program *program = context->getGLState().getProgram();
2722 if (!ValidateUniformCommonBase(context, program, uniformType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002723 {
2724 return false;
2725 }
2726
He Yunchaoced53ae2016-11-29 15:00:51 +08002727 GLenum targetBoolType = VariableBoolVectorType(uniformType);
Geoff Lang2ec386b2014-12-03 14:44:38 -05002728 bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
Jamie Madill36398922014-05-20 14:51:53 -04002729 if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
2730 {
Jamie Madill437fa652016-05-03 15:13:24 -04002731 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002732 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002733 }
2734
2735 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002736}
2737
He Yunchaoced53ae2016-11-29 15:00:51 +08002738bool ValidateUniformMatrix(gl::Context *context,
2739 GLenum matrixType,
2740 GLint location,
2741 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002742 GLboolean transpose)
2743{
2744 // Check for ES3 uniform entry points
2745 int rows = VariableRowCount(matrixType);
2746 int cols = VariableColumnCount(matrixType);
Martin Radev1be913c2016-07-11 17:59:16 +03002747 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002748 {
Jamie Madill437fa652016-05-03 15:13:24 -04002749 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002750 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002751 }
2752
Martin Radev1be913c2016-07-11 17:59:16 +03002753 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002754 {
Jamie Madill437fa652016-05-03 15:13:24 -04002755 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002756 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002757 }
2758
Jamie Madill62d31cb2015-09-11 13:25:51 -04002759 const LinkedUniform *uniform = nullptr;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002760 gl::Program *program = context->getGLState().getProgram();
2761 if (!ValidateUniformCommonBase(context, program, matrixType, location, count, &uniform))
Jamie Madill36398922014-05-20 14:51:53 -04002762 {
2763 return false;
2764 }
2765
2766 if (uniform->type != matrixType)
2767 {
Jamie Madill437fa652016-05-03 15:13:24 -04002768 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002769 return false;
Jamie Madill36398922014-05-20 14:51:53 -04002770 }
2771
2772 return true;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002773}
2774
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002775bool ValidateStateQuery(ValidationContext *context,
2776 GLenum pname,
2777 GLenum *nativeType,
2778 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002779{
2780 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2781 {
Jamie Madill437fa652016-05-03 15:13:24 -04002782 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04002783 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002784 }
2785
Jamie Madill0af26e12015-03-05 19:54:33 -05002786 const Caps &caps = context->getCaps();
2787
Jamie Madill893ab082014-05-16 16:56:10 -04002788 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2789 {
2790 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2791
Jamie Madill0af26e12015-03-05 19:54:33 -05002792 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002793 {
Jamie Madill437fa652016-05-03 15:13:24 -04002794 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002795 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002796 }
2797 }
2798
2799 switch (pname)
2800 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002801 case GL_TEXTURE_BINDING_2D:
2802 case GL_TEXTURE_BINDING_CUBE_MAP:
2803 case GL_TEXTURE_BINDING_3D:
2804 case GL_TEXTURE_BINDING_2D_ARRAY:
2805 break;
2806 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2807 if (!context->getExtensions().eglStreamConsumerExternal &&
2808 !context->getExtensions().eglImageExternal)
2809 {
2810 context->handleError(Error(GL_INVALID_ENUM,
2811 "Neither NV_EGL_stream_consumer_external nor "
2812 "GL_OES_EGL_image_external extensions enabled"));
2813 return false;
2814 }
2815 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002816
He Yunchaoced53ae2016-11-29 15:00:51 +08002817 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2818 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002819 {
Jamie Madill51f40ec2016-06-15 14:06:00 -04002820 if (context->getGLState().getReadFramebuffer()->checkStatus(
2821 context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002822 {
Jamie Madill437fa652016-05-03 15:13:24 -04002823 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002824 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002825 }
2826
Jamie Madill51f40ec2016-06-15 14:06:00 -04002827 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2828 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002829
2830 if (framebuffer->getReadBufferState() == GL_NONE)
2831 {
2832 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2833 return false;
2834 }
2835
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002836 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002837 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002838 {
Jamie Madill437fa652016-05-03 15:13:24 -04002839 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002840 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002841 }
2842 }
2843 break;
2844
He Yunchaoced53ae2016-11-29 15:00:51 +08002845 default:
2846 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002847 }
2848
2849 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002850 if (*numParams == 0)
2851 {
2852 return false;
2853 }
2854
2855 return true;
2856}
2857
2858bool ValidateRobustStateQuery(ValidationContext *context,
2859 GLenum pname,
2860 GLsizei bufSize,
2861 GLenum *nativeType,
2862 unsigned int *numParams)
2863{
2864 if (!ValidateRobustEntryPoint(context, bufSize))
2865 {
2866 return false;
2867 }
2868
2869 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2870 {
2871 return false;
2872 }
2873
2874 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002875 {
2876 return false;
2877 }
2878
2879 return true;
2880}
2881
Jamie Madillc29968b2016-01-20 11:17:23 -05002882bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2883 GLenum target,
2884 GLint level,
2885 GLenum internalformat,
2886 bool isSubImage,
2887 GLint xoffset,
2888 GLint yoffset,
2889 GLint zoffset,
2890 GLint x,
2891 GLint y,
2892 GLsizei width,
2893 GLsizei height,
2894 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002895 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002896{
Jamie Madill560a8d82014-05-21 13:06:20 -04002897 if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
2898 {
Jamie Madill437fa652016-05-03 15:13:24 -04002899 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002900 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002901 }
2902
He Yunchaoced53ae2016-11-29 15:00:51 +08002903 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2904 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002905 {
Jamie Madill437fa652016-05-03 15:13:24 -04002906 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002907 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002908 }
2909
2910 if (border != 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
2916 if (!ValidMipLevel(context, target, level))
2917 {
Jamie Madill437fa652016-05-03 15:13:24 -04002918 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04002919 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002920 }
2921
Jamie Madill51f40ec2016-06-15 14:06:00 -04002922 const auto &state = context->getGLState();
2923 auto readFramebuffer = state.getReadFramebuffer();
2924 if (readFramebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002925 {
Jamie Madill437fa652016-05-03 15:13:24 -04002926 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002927 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002928 }
2929
Jamie Madill51f40ec2016-06-15 14:06:00 -04002930 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context->getContextState()) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002931 {
Jamie Madill437fa652016-05-03 15:13:24 -04002932 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002933 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002934 }
2935
Martin Radev138064f2016-07-15 12:03:41 +03002936 if (readFramebuffer->getReadBufferState() == GL_NONE)
2937 {
2938 context->handleError(Error(GL_INVALID_OPERATION, "Read buffer is GL_NONE"));
2939 return false;
2940 }
2941
Geoff Langaae65a42014-05-26 12:43:44 -04002942 const gl::Caps &caps = context->getCaps();
2943
Geoff Langaae65a42014-05-26 12:43:44 -04002944 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002945 switch (target)
2946 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002947 case GL_TEXTURE_2D:
2948 maxDimension = caps.max2DTextureSize;
2949 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002950
He Yunchaoced53ae2016-11-29 15:00:51 +08002951 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2952 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2953 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2954 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2955 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2956 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2957 maxDimension = caps.maxCubeMapTextureSize;
2958 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002959
He Yunchaoced53ae2016-11-29 15:00:51 +08002960 case GL_TEXTURE_2D_ARRAY:
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_3D:
2965 maxDimension = caps.max3DTextureSize;
2966 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002967
He Yunchaoced53ae2016-11-29 15:00:51 +08002968 default:
2969 context->handleError(Error(GL_INVALID_ENUM));
2970 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002971 }
2972
Jamie Madillc29968b2016-01-20 11:17:23 -05002973 gl::Texture *texture =
2974 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002975 if (!texture)
2976 {
Jamie Madill437fa652016-05-03 15:13:24 -04002977 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002978 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002979 }
2980
Geoff Lang69cce582015-09-17 13:20:36 -04002981 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002982 {
Jamie Madill437fa652016-05-03 15:13:24 -04002983 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002984 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002985 }
2986
Geoff Lang5d601382014-07-22 15:14:06 -04002987 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
2988
2989 if (formatInfo.depthBits > 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002990 {
Jamie Madill437fa652016-05-03 15:13:24 -04002991 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04002992 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002993 }
2994
Geoff Langa9be0dc2014-12-17 12:34:40 -05002995 if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
Jamie Madill560a8d82014-05-21 13:06:20 -04002996 {
Jamie Madill437fa652016-05-03 15:13:24 -04002997 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05002998 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002999 }
3000
3001 if (isSubImage)
3002 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05003003 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
3004 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
3005 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04003006 {
Jamie Madill437fa652016-05-03 15:13:24 -04003007 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003008 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04003009 }
3010 }
Jamie Madill6f38f822014-06-06 17:12:20 -04003011 else
3012 {
Geoff Lang691e58c2014-12-19 17:03:25 -05003013 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04003014 {
Jamie Madill437fa652016-05-03 15:13:24 -04003015 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003016 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003017 }
3018
Geoff Langeb66a6e2016-10-31 13:06:12 -04003019 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04003020 {
Jamie Madill437fa652016-05-03 15:13:24 -04003021 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003022 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003023 }
3024
3025 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08003026 if (static_cast<int>(width) > maxLevelDimension ||
3027 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04003028 {
Jamie Madill437fa652016-05-03 15:13:24 -04003029 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003030 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04003031 }
3032 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003033
Jamie Madill0c8abca2016-07-22 20:21:26 -04003034 if (textureFormatOut)
3035 {
3036 *textureFormatOut = texture->getFormat(target, level);
3037 }
Jamie Madill560a8d82014-05-21 13:06:20 -04003038 return true;
3039}
3040
Jamie Madillf25855c2015-11-03 11:06:18 -05003041static bool ValidateDrawBase(ValidationContext *context,
3042 GLenum mode,
3043 GLsizei count,
3044 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003045{
Jamie Madill1aeb1312014-06-20 13:21:25 -04003046 switch (mode)
3047 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003048 case GL_POINTS:
3049 case GL_LINES:
3050 case GL_LINE_LOOP:
3051 case GL_LINE_STRIP:
3052 case GL_TRIANGLES:
3053 case GL_TRIANGLE_STRIP:
3054 case GL_TRIANGLE_FAN:
3055 break;
3056 default:
3057 context->handleError(Error(GL_INVALID_ENUM));
3058 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04003059 }
3060
Jamie Madill250d33f2014-06-06 17:09:03 -04003061 if (count < 0)
3062 {
Jamie Madill437fa652016-05-03 15:13:24 -04003063 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003064 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003065 }
3066
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003067 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04003068
Jamie Madill250d33f2014-06-06 17:09:03 -04003069 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003070 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003071 {
Jamie Madill437fa652016-05-03 15:13:24 -04003072 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003073 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003074 }
3075
Jamie Madill51f40ec2016-06-15 14:06:00 -04003076 Framebuffer *framebuffer = state.getDrawFramebuffer();
Geoff Lang3a86ad32015-09-01 11:47:05 -04003077 if (context->getLimitations().noSeparateStencilRefsAndMasks)
Jamie Madillac528012014-06-20 13:21:23 -04003078 {
Jinyoung Hur85769f02015-10-20 17:08:44 -04003079 const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer();
He Yunchaoced53ae2016-11-29 15:00:51 +08003080 GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0;
3081 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04003082 const DepthStencilState &depthStencilState = state.getDepthStencilState();
3083 if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
3084 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) ||
Geoff Lang3a86ad32015-09-01 11:47:05 -04003085 state.getStencilRef() != state.getStencilBackRef() ||
Jinyoung Hur85769f02015-10-20 17:08:44 -04003086 (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
3087 (depthStencilState.stencilBackMask & minimumRequiredStencilMask))
Geoff Lang3a86ad32015-09-01 11:47:05 -04003088 {
3089 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
3090 // Section 6.10 of the WebGL 1.0 spec
He Yunchaoced53ae2016-11-29 15:00:51 +08003091 ERR("This ANGLE implementation does not support separate front/back stencil "
Geoff Lang3a86ad32015-09-01 11:47:05 -04003092 "writemasks, reference values, or stencil mask values.");
Jamie Madill437fa652016-05-03 15:13:24 -04003093 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Lang3a86ad32015-09-01 11:47:05 -04003094 return false;
3095 }
Jamie Madillac528012014-06-20 13:21:23 -04003096 }
3097
Jamie Madill51f40ec2016-06-15 14:06:00 -04003098 if (framebuffer->checkStatus(context->getContextState()) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003099 {
Jamie Madill437fa652016-05-03 15:13:24 -04003100 context->handleError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003101 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04003102 }
3103
Geoff Lang7dd2e102014-11-10 15:19:26 -05003104 gl::Program *program = state.getProgram();
3105 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003106 {
Jamie Madill437fa652016-05-03 15:13:24 -04003107 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003108 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003109 }
3110
Geoff Lang7dd2e102014-11-10 15:19:26 -05003111 if (!program->validateSamplers(NULL, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04003112 {
Jamie Madill437fa652016-05-03 15:13:24 -04003113 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003114 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003115 }
3116
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003117 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08003118 for (unsigned int uniformBlockIndex = 0;
3119 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003120 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04003121 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08003122 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04003123 const OffsetBindingPointer<Buffer> &uniformBuffer =
3124 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003125
Geoff Lang5d124a62015-09-15 13:03:27 -04003126 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003127 {
3128 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003129 context->handleError(
3130 Error(GL_INVALID_OPERATION,
3131 "It is undefined behaviour to have a used but unbound uniform buffer."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003132 return false;
3133 }
3134
Geoff Lang5d124a62015-09-15 13:03:27 -04003135 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003136 if (uniformBufferSize == 0)
3137 {
3138 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07003139 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003140 }
3141
Jamie Madill62d31cb2015-09-11 13:25:51 -04003142 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003143 {
3144 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04003145 context->handleError(
3146 Error(GL_INVALID_OPERATION,
3147 "It is undefined behaviour to use a uniform buffer that is too small."));
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00003148 return false;
3149 }
3150 }
3151
Jamie Madill250d33f2014-06-06 17:09:03 -04003152 // No-op if zero count
3153 return (count > 0);
3154}
3155
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003156bool ValidateDrawArrays(ValidationContext *context,
3157 GLenum mode,
3158 GLint first,
3159 GLsizei count,
3160 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04003161{
Jamie Madillfd716582014-06-06 17:09:04 -04003162 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04003163 {
Jamie Madill437fa652016-05-03 15:13:24 -04003164 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003165 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003166 }
3167
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003168 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003169 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003170 if (curTransformFeedback && curTransformFeedback->isActive() &&
3171 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04003172 {
3173 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08003174 // that does not match the current transform feedback object's draw mode (if transform
3175 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04003176 // is active), (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003177 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003178 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003179 }
3180
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003181 if (!ValidateDrawBase(context, mode, count, primcount))
3182 {
3183 return false;
3184 }
3185
Corentin Wallez92db6942016-12-09 13:10:36 -05003186 CheckedNumeric<GLint> maxVertex = first;
3187 maxVertex += count;
3188 maxVertex -= 1;
3189
3190 if (!maxVertex.IsValid())
3191 {
3192 context->handleError(Error(GL_INVALID_OPERATION, "Integer overflow."));
3193 return false;
3194 }
3195
3196 if (!ValidateDrawAttribs(context, primcount, maxVertex.ValueOrDie(), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003197 {
3198 return false;
3199 }
3200
3201 return true;
3202}
3203
He Yunchaoced53ae2016-11-29 15:00:51 +08003204bool ValidateDrawArraysInstanced(Context *context,
3205 GLenum mode,
3206 GLint first,
3207 GLsizei count,
3208 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003209{
3210 if (primcount < 0)
3211 {
Jamie Madill437fa652016-05-03 15:13:24 -04003212 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003213 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003214 }
3215
Jamie Madill2b976812014-08-25 15:47:49 -04003216 if (!ValidateDrawArrays(context, mode, first, count, primcount))
Jamie Madillfd716582014-06-06 17:09:04 -04003217 {
3218 return false;
3219 }
3220
3221 // No-op if zero primitive count
3222 return (primcount > 0);
3223}
3224
Geoff Lang87a93302014-09-16 13:29:43 -04003225static bool ValidateDrawInstancedANGLE(Context *context)
3226{
3227 // Verify there is at least one active attribute with a divisor of zero
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003228 const gl::State &state = context->getGLState();
Geoff Lang87a93302014-09-16 13:29:43 -04003229
Geoff Lang7dd2e102014-11-10 15:19:26 -05003230 gl::Program *program = state.getProgram();
Geoff Lang87a93302014-09-16 13:29:43 -04003231
3232 const VertexArray *vao = state.getVertexArray();
Jamie Madill63805b42015-08-25 13:17:39 -04003233 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
Geoff Lang87a93302014-09-16 13:29:43 -04003234 {
3235 const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
Jamie Madill63805b42015-08-25 13:17:39 -04003236 if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0)
Geoff Lang87a93302014-09-16 13:29:43 -04003237 {
3238 return true;
3239 }
3240 }
3241
Jamie Madill437fa652016-05-03 15:13:24 -04003242 context->handleError(Error(GL_INVALID_OPERATION,
3243 "ANGLE_instanced_arrays requires that at least one active attribute"
3244 "has a divisor of zero."));
Geoff Lang87a93302014-09-16 13:29:43 -04003245 return false;
3246}
3247
He Yunchaoced53ae2016-11-29 15:00:51 +08003248bool ValidateDrawArraysInstancedANGLE(Context *context,
3249 GLenum mode,
3250 GLint first,
3251 GLsizei count,
3252 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003253{
3254 if (!ValidateDrawInstancedANGLE(context))
3255 {
3256 return false;
3257 }
3258
3259 return ValidateDrawArraysInstanced(context, mode, first, count, primcount);
3260}
3261
Jamie Madillf25855c2015-11-03 11:06:18 -05003262bool ValidateDrawElements(ValidationContext *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003263 GLenum mode,
3264 GLsizei count,
3265 GLenum type,
3266 const GLvoid *indices,
3267 GLsizei primcount,
3268 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003269{
Jamie Madill250d33f2014-06-06 17:09:03 -04003270 switch (type)
3271 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003272 case GL_UNSIGNED_BYTE:
3273 case GL_UNSIGNED_SHORT:
3274 break;
3275 case GL_UNSIGNED_INT:
3276 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3277 {
3278 context->handleError(Error(GL_INVALID_ENUM));
3279 return false;
3280 }
3281 break;
3282 default:
3283 context->handleError(Error(GL_INVALID_ENUM));
3284 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003285 }
3286
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003287 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003288
3289 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003290 if (curTransformFeedback && curTransformFeedback->isActive() &&
3291 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003292 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003293 // It is an invalid operation to call DrawElements, DrawRangeElements or
3294 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003295 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Jamie Madill437fa652016-05-03 15:13:24 -04003296 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003297 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003298 }
3299
3300 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003301 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003302 {
Jamie Madill437fa652016-05-03 15:13:24 -04003303 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003304 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003305 }
3306
He Yunchaoced53ae2016-11-29 15:00:51 +08003307 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003308 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madill2b976812014-08-25 15:47:49 -04003309 if (!indices && !elementArrayBuffer)
Jamie Madilld4cfa572014-07-08 10:00:32 -04003310 {
Jamie Madill437fa652016-05-03 15:13:24 -04003311 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003312 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04003313 }
3314
Jamie Madillae3000b2014-08-25 15:47:51 -04003315 if (elementArrayBuffer)
3316 {
3317 const gl::Type &typeInfo = gl::GetTypeInfo(type);
3318
3319 GLint64 offset = reinterpret_cast<GLint64>(indices);
He Yunchaoced53ae2016-11-29 15:00:51 +08003320 GLint64 byteCount =
3321 static_cast<GLint64>(typeInfo.bytes) * static_cast<GLint64>(count) + offset;
Jamie Madillae3000b2014-08-25 15:47:51 -04003322
3323 // check for integer overflows
3324 if (static_cast<GLuint>(count) > (std::numeric_limits<GLuint>::max() / typeInfo.bytes) ||
3325 byteCount > static_cast<GLint64>(std::numeric_limits<GLuint>::max()))
3326 {
Jamie Madill437fa652016-05-03 15:13:24 -04003327 context->handleError(Error(GL_OUT_OF_MEMORY));
Geoff Langb1196682014-07-23 13:47:29 -04003328 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003329 }
3330
3331 // Check for reading past the end of the bound buffer object
3332 if (byteCount > elementArrayBuffer->getSize())
3333 {
Jamie Madill437fa652016-05-03 15:13:24 -04003334 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003335 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003336 }
3337 }
3338 else if (!indices)
3339 {
3340 // Catch this programming error here
Jamie Madill437fa652016-05-03 15:13:24 -04003341 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003342 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003343 }
3344
Corentin Wallez18a2fb32015-08-10 12:58:14 -07003345 if (!ValidateDrawBase(context, mode, count, primcount))
3346 {
3347 return false;
3348 }
3349
Jamie Madill2b976812014-08-25 15:47:49 -04003350 // Use max index to validate if our vertex buffers are large enough for the pull.
3351 // TODO: offer fast path, with disabled index validation.
3352 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3353 if (elementArrayBuffer)
3354 {
Jacek Cabana5521de2014-10-01 17:23:46 +02003355 uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
Geoff Lang3edfe032015-09-04 16:38:24 -04003356 Error error =
3357 elementArrayBuffer->getIndexRange(type, static_cast<size_t>(offset), count,
3358 state.isPrimitiveRestartEnabled(), indexRangeOut);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003359 if (error.isError())
Jamie Madill2b976812014-08-25 15:47:49 -04003360 {
Jamie Madill437fa652016-05-03 15:13:24 -04003361 context->handleError(error);
Geoff Lang520c4ae2015-05-05 13:12:36 -04003362 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003363 }
3364 }
3365 else
3366 {
Geoff Lang3edfe032015-09-04 16:38:24 -04003367 *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled());
Jamie Madill2b976812014-08-25 15:47:49 -04003368 }
3369
Jamie Madille79b1e12015-11-04 16:36:37 -05003370 // If we use an index greater than our maximum supported index range, return an error.
3371 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3372 // return an error if possible here.
3373 if (static_cast<GLuint64>(indexRangeOut->end) >= context->getCaps().maxElementIndex)
3374 {
Jamie Madill437fa652016-05-03 15:13:24 -04003375 context->handleError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage));
Jamie Madille79b1e12015-11-04 16:36:37 -05003376 return false;
3377 }
3378
Corentin Wallez92db6942016-12-09 13:10:36 -05003379 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOut->end),
3380 static_cast<GLint>(indexRangeOut->vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003381 {
3382 return false;
3383 }
3384
Geoff Lang3edfe032015-09-04 16:38:24 -04003385 // No op if there are no real indices in the index data (all are primitive restart).
3386 return (indexRangeOut->vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003387}
3388
Geoff Langb1196682014-07-23 13:47:29 -04003389bool ValidateDrawElementsInstanced(Context *context,
Geoff Lang3edfe032015-09-04 16:38:24 -04003390 GLenum mode,
3391 GLsizei count,
3392 GLenum type,
3393 const GLvoid *indices,
3394 GLsizei primcount,
3395 IndexRange *indexRangeOut)
Jamie Madillfd716582014-06-06 17:09:04 -04003396{
3397 if (primcount < 0)
3398 {
Jamie Madill437fa652016-05-03 15:13:24 -04003399 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003400 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04003401 }
3402
Jamie Madill2b976812014-08-25 15:47:49 -04003403 if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut))
Jamie Madillfd716582014-06-06 17:09:04 -04003404 {
3405 return false;
3406 }
3407
3408 // No-op zero primitive count
3409 return (primcount > 0);
Jamie Madill250d33f2014-06-06 17:09:03 -04003410}
3411
Geoff Lang3edfe032015-09-04 16:38:24 -04003412bool ValidateDrawElementsInstancedANGLE(Context *context,
3413 GLenum mode,
3414 GLsizei count,
3415 GLenum type,
3416 const GLvoid *indices,
3417 GLsizei primcount,
3418 IndexRange *indexRangeOut)
Geoff Lang87a93302014-09-16 13:29:43 -04003419{
3420 if (!ValidateDrawInstancedANGLE(context))
3421 {
3422 return false;
3423 }
3424
He Yunchaoced53ae2016-11-29 15:00:51 +08003425 return ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount,
3426 indexRangeOut);
Geoff Lang87a93302014-09-16 13:29:43 -04003427}
3428
He Yunchaoced53ae2016-11-29 15:00:51 +08003429bool ValidateFramebufferTextureBase(Context *context,
3430 GLenum target,
3431 GLenum attachment,
3432 GLuint texture,
3433 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003434{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003435 if (!ValidFramebufferTarget(target))
3436 {
Jamie Madill437fa652016-05-03 15:13:24 -04003437 context->handleError(Error(GL_INVALID_ENUM));
Geoff Langb1196682014-07-23 13:47:29 -04003438 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003439 }
3440
3441 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003442 {
3443 return false;
3444 }
3445
Jamie Madill55ec3b12014-07-03 10:38:57 -04003446 if (texture != 0)
3447 {
3448 gl::Texture *tex = context->getTexture(texture);
3449
3450 if (tex == NULL)
3451 {
Jamie Madill437fa652016-05-03 15:13:24 -04003452 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003453 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003454 }
3455
3456 if (level < 0)
3457 {
Jamie Madill437fa652016-05-03 15:13:24 -04003458 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003459 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003460 }
3461 }
3462
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003463 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003464 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003465
Jamie Madill84115c92015-04-23 15:00:07 -04003466 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003467 {
Jamie Madill437fa652016-05-03 15:13:24 -04003468 context->handleError(
3469 Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments"));
Geoff Langb1196682014-07-23 13:47:29 -04003470 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003471 }
3472
3473 return true;
3474}
3475
He Yunchaoced53ae2016-11-29 15:00:51 +08003476bool ValidateFramebufferTexture2D(Context *context,
3477 GLenum target,
3478 GLenum attachment,
3479 GLenum textarget,
3480 GLuint texture,
3481 GLint level)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003482{
He Yunchaoced53ae2016-11-29 15:00:51 +08003483 // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
3484 // extension
Martin Radev1be913c2016-07-11 17:59:16 +03003485 if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
3486 level != 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003487 {
Jamie Madill437fa652016-05-03 15:13:24 -04003488 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003489 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003490 }
3491
3492 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
Jamie Madill570f7c82014-07-03 10:38:54 -04003493 {
3494 return false;
3495 }
3496
Jamie Madill55ec3b12014-07-03 10:38:57 -04003497 if (texture != 0)
3498 {
3499 gl::Texture *tex = context->getTexture(texture);
3500 ASSERT(tex);
3501
Jamie Madill2a6564e2014-07-11 09:53:19 -04003502 const gl::Caps &caps = context->getCaps();
3503
Jamie Madill55ec3b12014-07-03 10:38:57 -04003504 switch (textarget)
3505 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003506 case GL_TEXTURE_2D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003507 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003508 if (level > gl::log2(caps.max2DTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003509 {
Jamie Madill437fa652016-05-03 15:13:24 -04003510 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003511 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003512 }
3513 if (tex->getTarget() != GL_TEXTURE_2D)
3514 {
Jamie Madill437fa652016-05-03 15:13:24 -04003515 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003516 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003517 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003518 }
3519 break;
3520
He Yunchaoced53ae2016-11-29 15:00:51 +08003521 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3522 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3523 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3524 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3525 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3526 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
Jamie Madill55ec3b12014-07-03 10:38:57 -04003527 {
Jamie Madill2a6564e2014-07-11 09:53:19 -04003528 if (level > gl::log2(caps.maxCubeMapTextureSize))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003529 {
Jamie Madill437fa652016-05-03 15:13:24 -04003530 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003531 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003532 }
3533 if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
3534 {
Jamie Madill437fa652016-05-03 15:13:24 -04003535 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003536 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003537 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003538 }
3539 break;
3540
He Yunchaoced53ae2016-11-29 15:00:51 +08003541 default:
3542 context->handleError(Error(GL_INVALID_ENUM));
3543 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003544 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05003545
Jamie Madilla3944d42016-07-22 22:13:26 -04003546 const Format &format = tex->getFormat(textarget, level);
3547 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05003548 {
Jamie Madill437fa652016-05-03 15:13:24 -04003549 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa9be0dc2014-12-17 12:34:40 -05003550 return false;
3551 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04003552 }
3553
Jamie Madill570f7c82014-07-03 10:38:54 -04003554 return true;
3555}
3556
Geoff Langb1196682014-07-23 13:47:29 -04003557bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003558{
3559 if (program == 0)
3560 {
Jamie Madill437fa652016-05-03 15:13:24 -04003561 context->handleError(Error(GL_INVALID_VALUE));
Geoff Langb1196682014-07-23 13:47:29 -04003562 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003563 }
3564
Dian Xiang769769a2015-09-09 15:20:08 -07003565 gl::Program *programObject = GetValidProgram(context, program);
3566 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003567 {
3568 return false;
3569 }
3570
Jamie Madill0063c512014-08-25 15:47:53 -04003571 if (!programObject || !programObject->isLinked())
3572 {
Jamie Madill437fa652016-05-03 15:13:24 -04003573 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003574 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003575 }
3576
Geoff Lang7dd2e102014-11-10 15:19:26 -05003577 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003578 {
Jamie Madill437fa652016-05-03 15:13:24 -04003579 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langb1196682014-07-23 13:47:29 -04003580 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003581 }
3582
Jamie Madill0063c512014-08-25 15:47:53 -04003583 return true;
3584}
3585
He Yunchaoced53ae2016-11-29 15:00:51 +08003586bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
Jamie Madill78f41802014-08-25 15:47:55 -04003587{
3588 return ValidateGetUniformBase(context, program, location);
3589}
3590
He Yunchaoced53ae2016-11-29 15:00:51 +08003591bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003592{
Jamie Madill78f41802014-08-25 15:47:55 -04003593 return ValidateGetUniformBase(context, program, location);
3594}
3595
Geoff Langf41d0ee2016-10-07 13:04:23 -04003596static bool ValidateSizedGetUniform(Context *context,
3597 GLuint program,
3598 GLint location,
3599 GLsizei bufSize,
3600 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003601{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003602 if (length)
3603 {
3604 *length = 0;
3605 }
3606
Jamie Madill78f41802014-08-25 15:47:55 -04003607 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003608 {
Jamie Madill78f41802014-08-25 15:47:55 -04003609 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003610 }
3611
Geoff Langf41d0ee2016-10-07 13:04:23 -04003612 if (bufSize < 0)
3613 {
3614 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
3615 return false;
3616 }
3617
Jamie Madilla502c742014-08-28 17:19:13 -04003618 gl::Program *programObject = context->getProgram(program);
3619 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003620
Jamie Madill78f41802014-08-25 15:47:55 -04003621 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003622 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003623 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003624 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003625 {
Geoff Langf41d0ee2016-10-07 13:04:23 -04003626 context->handleError(
3627 Error(GL_INVALID_OPERATION, "bufSize of at least %u is required.", requiredBytes));
Geoff Langb1196682014-07-23 13:47:29 -04003628 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003629 }
3630
Geoff Langf41d0ee2016-10-07 13:04:23 -04003631 if (length)
3632 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003633 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003634 }
3635
Jamie Madill0063c512014-08-25 15:47:53 -04003636 return true;
3637}
3638
He Yunchaoced53ae2016-11-29 15:00:51 +08003639bool ValidateGetnUniformfvEXT(Context *context,
3640 GLuint program,
3641 GLint location,
3642 GLsizei bufSize,
3643 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003644{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003645 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003646}
3647
He Yunchaoced53ae2016-11-29 15:00:51 +08003648bool ValidateGetnUniformivEXT(Context *context,
3649 GLuint program,
3650 GLint location,
3651 GLsizei bufSize,
3652 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003653{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003654 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3655}
3656
3657bool ValidateGetUniformfvRobustANGLE(Context *context,
3658 GLuint program,
3659 GLint location,
3660 GLsizei bufSize,
3661 GLsizei *length,
3662 GLfloat *params)
3663{
3664 if (!ValidateRobustEntryPoint(context, bufSize))
3665 {
3666 return false;
3667 }
3668
3669 // bufSize is validated in ValidateSizedGetUniform
3670 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3671}
3672
3673bool ValidateGetUniformivRobustANGLE(Context *context,
3674 GLuint program,
3675 GLint location,
3676 GLsizei bufSize,
3677 GLsizei *length,
3678 GLint *params)
3679{
3680 if (!ValidateRobustEntryPoint(context, bufSize))
3681 {
3682 return false;
3683 }
3684
3685 // bufSize is validated in ValidateSizedGetUniform
3686 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3687}
3688
3689bool ValidateGetUniformuivRobustANGLE(Context *context,
3690 GLuint program,
3691 GLint location,
3692 GLsizei bufSize,
3693 GLsizei *length,
3694 GLuint *params)
3695{
3696 if (!ValidateRobustEntryPoint(context, bufSize))
3697 {
3698 return false;
3699 }
3700
3701 if (context->getClientMajorVersion() < 3)
3702 {
3703 context->handleError(
3704 Error(GL_INVALID_OPERATION, "Entry point requires at least OpenGL ES 3.0."));
3705 return false;
3706 }
3707
3708 // bufSize is validated in ValidateSizedGetUniform
3709 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003710}
3711
He Yunchaoced53ae2016-11-29 15:00:51 +08003712bool ValidateDiscardFramebufferBase(Context *context,
3713 GLenum target,
3714 GLsizei numAttachments,
3715 const GLenum *attachments,
3716 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003717{
3718 if (numAttachments < 0)
3719 {
Jamie Madill437fa652016-05-03 15:13:24 -04003720 context->handleError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero"));
Austin Kinross08332632015-05-05 13:35:47 -07003721 return false;
3722 }
3723
3724 for (GLsizei i = 0; i < numAttachments; ++i)
3725 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003726 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003727 {
3728 if (defaultFramebuffer)
3729 {
Jamie Madill437fa652016-05-03 15:13:24 -04003730 context->handleError(Error(
3731 GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound"));
Austin Kinross08332632015-05-05 13:35:47 -07003732 return false;
3733 }
3734
3735 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3736 {
Jamie Madill437fa652016-05-03 15:13:24 -04003737 context->handleError(Error(GL_INVALID_OPERATION,
3738 "Requested color attachment is greater than the maximum "
3739 "supported color attachments"));
Austin Kinross08332632015-05-05 13:35:47 -07003740 return false;
3741 }
3742 }
3743 else
3744 {
3745 switch (attachments[i])
3746 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003747 case GL_DEPTH_ATTACHMENT:
3748 case GL_STENCIL_ATTACHMENT:
3749 case GL_DEPTH_STENCIL_ATTACHMENT:
3750 if (defaultFramebuffer)
3751 {
3752 context->handleError(
3753 Error(GL_INVALID_ENUM,
3754 "Invalid attachment when the default framebuffer is bound"));
3755 return false;
3756 }
3757 break;
3758 case GL_COLOR:
3759 case GL_DEPTH:
3760 case GL_STENCIL:
3761 if (!defaultFramebuffer)
3762 {
3763 context->handleError(
3764 Error(GL_INVALID_ENUM,
3765 "Invalid attachment when the default framebuffer is not bound"));
3766 return false;
3767 }
3768 break;
3769 default:
3770 context->handleError(Error(GL_INVALID_ENUM, "Invalid attachment"));
Austin Kinross08332632015-05-05 13:35:47 -07003771 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003772 }
3773 }
3774 }
3775
3776 return true;
3777}
3778
Austin Kinross6ee1e782015-05-29 17:05:37 -07003779bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3780{
3781 // Note that debug marker calls must not set error state
3782
3783 if (length < 0)
3784 {
3785 return false;
3786 }
3787
3788 if (marker == nullptr)
3789 {
3790 return false;
3791 }
3792
3793 return true;
3794}
3795
3796bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3797{
3798 // Note that debug marker calls must not set error state
3799
3800 if (length < 0)
3801 {
3802 return false;
3803 }
3804
3805 if (length > 0 && marker == nullptr)
3806 {
3807 return false;
3808 }
3809
3810 return true;
3811}
3812
Geoff Langdcab33b2015-07-21 13:03:16 -04003813bool ValidateEGLImageTargetTexture2DOES(Context *context,
3814 egl::Display *display,
3815 GLenum target,
3816 egl::Image *image)
3817{
Geoff Langa8406172015-07-21 16:53:39 -04003818 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3819 {
Jamie Madill437fa652016-05-03 15:13:24 -04003820 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003821 return false;
3822 }
3823
3824 switch (target)
3825 {
3826 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003827 if (!context->getExtensions().eglImage)
3828 {
3829 context->handleError(Error(
3830 GL_INVALID_ENUM, "GL_TEXTURE_2D texture target requires GL_OES_EGL_image."));
3831 }
3832 break;
3833
3834 case GL_TEXTURE_EXTERNAL_OES:
3835 if (!context->getExtensions().eglImageExternal)
3836 {
3837 context->handleError(Error(
3838 GL_INVALID_ENUM,
3839 "GL_TEXTURE_EXTERNAL_OES texture target requires GL_OES_EGL_image_external."));
3840 }
Geoff Langa8406172015-07-21 16:53:39 -04003841 break;
3842
3843 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003844 context->handleError(Error(GL_INVALID_ENUM, "invalid texture target."));
Geoff Langa8406172015-07-21 16:53:39 -04003845 return false;
3846 }
3847
3848 if (!display->isValidImage(image))
3849 {
Jamie Madill437fa652016-05-03 15:13:24 -04003850 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003851 return false;
3852 }
3853
3854 if (image->getSamples() > 0)
3855 {
Jamie Madill437fa652016-05-03 15:13:24 -04003856 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003857 "cannot create a 2D texture from a multisampled EGL image."));
3858 return false;
3859 }
3860
Jamie Madilla3944d42016-07-22 22:13:26 -04003861 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003862 if (!textureCaps.texturable)
3863 {
Jamie Madill437fa652016-05-03 15:13:24 -04003864 context->handleError(Error(GL_INVALID_OPERATION,
Geoff Langa8406172015-07-21 16:53:39 -04003865 "EGL image internal format is not supported as a texture."));
3866 return false;
3867 }
3868
Geoff Langdcab33b2015-07-21 13:03:16 -04003869 return true;
3870}
3871
3872bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
3873 egl::Display *display,
3874 GLenum target,
3875 egl::Image *image)
3876{
Geoff Langa8406172015-07-21 16:53:39 -04003877 if (!context->getExtensions().eglImage)
3878 {
Jamie Madill437fa652016-05-03 15:13:24 -04003879 context->handleError(Error(GL_INVALID_OPERATION));
Geoff Langa8406172015-07-21 16:53:39 -04003880 return false;
3881 }
3882
3883 switch (target)
3884 {
3885 case GL_RENDERBUFFER:
3886 break;
3887
3888 default:
Jamie Madill437fa652016-05-03 15:13:24 -04003889 context->handleError(Error(GL_INVALID_ENUM, "invalid renderbuffer target."));
Geoff Langa8406172015-07-21 16:53:39 -04003890 return false;
3891 }
3892
3893 if (!display->isValidImage(image))
3894 {
Jamie Madill437fa652016-05-03 15:13:24 -04003895 context->handleError(Error(GL_INVALID_VALUE, "EGL image is not valid."));
Geoff Langa8406172015-07-21 16:53:39 -04003896 return false;
3897 }
3898
Jamie Madilla3944d42016-07-22 22:13:26 -04003899 const TextureCaps &textureCaps = context->getTextureCaps().get(image->getFormat().asSized());
Geoff Langa8406172015-07-21 16:53:39 -04003900 if (!textureCaps.renderable)
3901 {
Jamie Madill437fa652016-05-03 15:13:24 -04003902 context->handleError(Error(
Geoff Langa8406172015-07-21 16:53:39 -04003903 GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer."));
3904 return false;
3905 }
3906
Geoff Langdcab33b2015-07-21 13:03:16 -04003907 return true;
3908}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003909
3910bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3911{
Geoff Lang36167ab2015-12-07 10:27:14 -05003912 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003913 {
3914 // The default VAO should always exist
3915 ASSERT(array != 0);
Jamie Madill437fa652016-05-03 15:13:24 -04003916 context->handleError(Error(GL_INVALID_OPERATION));
Austin Kinrossbc781f32015-10-26 09:27:38 -07003917 return false;
3918 }
3919
3920 return true;
3921}
3922
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003923bool ValidateLinkProgram(Context *context, GLuint program)
3924{
3925 if (context->hasActiveTransformFeedback(program))
3926 {
3927 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003928 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003929 "Cannot link program while program is associated with an active "
3930 "transform feedback object."));
3931 return false;
3932 }
3933 return true;
3934}
3935
Geoff Langc5629752015-12-07 16:29:04 -05003936bool ValidateProgramBinaryBase(Context *context,
3937 GLuint program,
3938 GLenum binaryFormat,
3939 const void *binary,
3940 GLint length)
3941{
3942 Program *programObject = GetValidProgram(context, program);
3943 if (programObject == nullptr)
3944 {
3945 return false;
3946 }
3947
3948 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3949 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3950 programBinaryFormats.end())
3951 {
Jamie Madill437fa652016-05-03 15:13:24 -04003952 context->handleError(Error(GL_INVALID_ENUM, "Program binary format is not valid."));
Geoff Langc5629752015-12-07 16:29:04 -05003953 return false;
3954 }
3955
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003956 if (context->hasActiveTransformFeedback(program))
3957 {
3958 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04003959 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003960 "Cannot change program binary while program is associated with "
3961 "an active transform feedback object."));
3962 return false;
3963 }
3964
Geoff Langc5629752015-12-07 16:29:04 -05003965 return true;
3966}
3967
3968bool ValidateGetProgramBinaryBase(Context *context,
3969 GLuint program,
3970 GLsizei bufSize,
3971 GLsizei *length,
3972 GLenum *binaryFormat,
3973 void *binary)
3974{
3975 Program *programObject = GetValidProgram(context, program);
3976 if (programObject == nullptr)
3977 {
3978 return false;
3979 }
3980
3981 if (!programObject->isLinked())
3982 {
Jamie Madill437fa652016-05-03 15:13:24 -04003983 context->handleError(Error(GL_INVALID_OPERATION, "Program is not linked."));
Geoff Langc5629752015-12-07 16:29:04 -05003984 return false;
3985 }
3986
3987 return true;
3988}
Jamie Madillc29968b2016-01-20 11:17:23 -05003989
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003990bool ValidateUseProgram(Context *context, GLuint program)
3991{
3992 if (program != 0)
3993 {
3994 Program *programObject = context->getProgram(program);
3995 if (!programObject)
3996 {
3997 // ES 3.1.0 section 7.3 page 72
3998 if (context->getShader(program))
3999 {
Jamie Madill437fa652016-05-03 15:13:24 -04004000 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004001 Error(GL_INVALID_OPERATION,
4002 "Attempted to use a single shader instead of a shader program."));
4003 return false;
4004 }
4005 else
4006 {
Jamie Madill437fa652016-05-03 15:13:24 -04004007 context->handleError(Error(GL_INVALID_VALUE, "Program invalid."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004008 return false;
4009 }
4010 }
4011 if (!programObject->isLinked())
4012 {
Jamie Madill437fa652016-05-03 15:13:24 -04004013 context->handleError(Error(GL_INVALID_OPERATION, "Program not linked."));
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004014 return false;
4015 }
4016 }
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004017 if (context->getGLState().isTransformFeedbackActiveUnpaused())
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004018 {
4019 // ES 3.0.4 section 2.15 page 91
Jamie Madill437fa652016-05-03 15:13:24 -04004020 context->handleError(
Olli Etuahoc3e55a42016-03-09 16:29:18 +02004021 Error(GL_INVALID_OPERATION,
4022 "Cannot change active program while transform feedback is unpaused."));
4023 return false;
4024 }
4025
4026 return true;
4027}
4028
Jamie Madillc29968b2016-01-20 11:17:23 -05004029bool ValidateCopyTexImage2D(ValidationContext *context,
4030 GLenum target,
4031 GLint level,
4032 GLenum internalformat,
4033 GLint x,
4034 GLint y,
4035 GLsizei width,
4036 GLsizei height,
4037 GLint border)
4038{
Martin Radev1be913c2016-07-11 17:59:16 +03004039 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004040 {
4041 return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
4042 0, x, y, width, height, border);
4043 }
4044
Martin Radev1be913c2016-07-11 17:59:16 +03004045 ASSERT(context->getClientMajorVersion() == 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004046 return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
4047 0, x, y, width, height, border);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04004048}
Jamie Madillc29968b2016-01-20 11:17:23 -05004049
4050bool ValidateFramebufferRenderbuffer(Context *context,
4051 GLenum target,
4052 GLenum attachment,
4053 GLenum renderbuffertarget,
4054 GLuint renderbuffer)
4055{
4056 if (!ValidFramebufferTarget(target) ||
4057 (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
4058 {
Jamie Madill437fa652016-05-03 15:13:24 -04004059 context->handleError(Error(GL_INVALID_ENUM));
Jamie Madillc29968b2016-01-20 11:17:23 -05004060 return false;
4061 }
4062
4063 return ValidateFramebufferRenderbufferParameters(context, target, attachment,
4064 renderbuffertarget, renderbuffer);
4065}
4066
4067bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
4068{
4069 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
4070 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
4071 {
Jamie Madill437fa652016-05-03 15:13:24 -04004072 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004073 Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS"));
4074 return false;
4075 }
4076
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004077 ASSERT(context->getGLState().getDrawFramebuffer());
4078 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05004079 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
4080
4081 // This should come first before the check for the default frame buffer
4082 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
4083 // rather than INVALID_OPERATION
4084 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
4085 {
4086 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
4087
4088 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02004089 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
4090 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05004091 {
4092 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02004093 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
4094 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
4095 // 3.1 is still a bit ambiguous about the error, but future specs are
4096 // expected to clarify that GL_INVALID_ENUM is the correct error.
Jamie Madill437fa652016-05-03 15:13:24 -04004097 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer value"));
Olli Etuaho84c9f592016-03-09 14:37:25 +02004098 return false;
4099 }
4100 else if (bufs[colorAttachment] >= maxColorAttachment)
4101 {
Jamie Madill437fa652016-05-03 15:13:24 -04004102 context->handleError(
Olli Etuaho84c9f592016-03-09 14:37:25 +02004103 Error(GL_INVALID_OPERATION, "Buffer value is greater than MAX_DRAW_BUFFERS"));
Jamie Madillc29968b2016-01-20 11:17:23 -05004104 return false;
4105 }
4106 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
4107 frameBufferId != 0)
4108 {
4109 // INVALID_OPERATION-GL is bound to buffer and ith argument
4110 // is not COLOR_ATTACHMENTi or NONE
Jamie Madill437fa652016-05-03 15:13:24 -04004111 context->handleError(
Jamie Madillc29968b2016-01-20 11:17:23 -05004112 Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE"));
4113 return false;
4114 }
4115 }
4116
4117 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
4118 // and n is not 1 or bufs is bound to value other than BACK and NONE
4119 if (frameBufferId == 0)
4120 {
4121 if (n != 1)
4122 {
Jamie Madill437fa652016-05-03 15:13:24 -04004123 context->handleError(Error(GL_INVALID_OPERATION,
Jamie Madillc29968b2016-01-20 11:17:23 -05004124 "n must be 1 when GL is bound to the default framebuffer"));
4125 return false;
4126 }
4127
4128 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
4129 {
Jamie Madill437fa652016-05-03 15:13:24 -04004130 context->handleError(Error(
Jamie Madillc29968b2016-01-20 11:17:23 -05004131 GL_INVALID_OPERATION,
4132 "Only NONE or BACK are valid values when drawing to the default framebuffer"));
4133 return false;
4134 }
4135 }
4136
4137 return true;
4138}
4139
4140bool ValidateCopyTexSubImage2D(Context *context,
4141 GLenum target,
4142 GLint level,
4143 GLint xoffset,
4144 GLint yoffset,
4145 GLint x,
4146 GLint y,
4147 GLsizei width,
4148 GLsizei height)
4149{
Martin Radev1be913c2016-07-11 17:59:16 +03004150 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05004151 {
4152 return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
4153 yoffset, x, y, width, height, 0);
4154 }
4155
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05004156 return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
4157 yoffset, 0, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05004158}
4159
Geoff Lang496c02d2016-10-20 11:38:11 -07004160bool ValidateGetBufferPointervBase(Context *context,
4161 GLenum target,
4162 GLenum pname,
4163 GLsizei *length,
4164 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03004165{
Geoff Lang496c02d2016-10-20 11:38:11 -07004166 if (length)
4167 {
4168 *length = 0;
4169 }
4170
4171 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
4172 {
4173 context->handleError(
4174 Error(GL_INVALID_OPERATION,
4175 "Context does not support OpenGL ES 3.0 or GL_OES_map_buffer is not enabled."));
4176 return false;
4177 }
4178
Olli Etuaho4f667482016-03-30 15:56:35 +03004179 if (!ValidBufferTarget(context, target))
4180 {
Jamie Madill437fa652016-05-03 15:13:24 -04004181 context->handleError(Error(GL_INVALID_ENUM, "Buffer target not valid: 0x%X", target));
Olli Etuaho4f667482016-03-30 15:56:35 +03004182 return false;
4183 }
4184
Geoff Lang496c02d2016-10-20 11:38:11 -07004185 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03004186 {
Geoff Lang496c02d2016-10-20 11:38:11 -07004187 case GL_BUFFER_MAP_POINTER:
4188 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03004189
Geoff Lang496c02d2016-10-20 11:38:11 -07004190 default:
4191 context->handleError(Error(GL_INVALID_ENUM, "Unknown pname."));
4192 return false;
4193 }
Olli Etuaho4f667482016-03-30 15:56:35 +03004194
4195 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
4196 // target bound to zero generate an INVALID_OPERATION error."
4197 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07004198 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03004199 {
Jamie Madill437fa652016-05-03 15:13:24 -04004200 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004201 Error(GL_INVALID_OPERATION, "Can not get pointer for reserved buffer name zero."));
4202 return false;
4203 }
4204
Geoff Lang496c02d2016-10-20 11:38:11 -07004205 if (length)
4206 {
4207 *length = 1;
4208 }
4209
Olli Etuaho4f667482016-03-30 15:56:35 +03004210 return true;
4211}
4212
4213bool ValidateUnmapBufferBase(Context *context, GLenum target)
4214{
4215 if (!ValidBufferTarget(context, target))
4216 {
Jamie Madill437fa652016-05-03 15:13:24 -04004217 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004218 return false;
4219 }
4220
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004221 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004222
4223 if (buffer == nullptr || !buffer->isMapped())
4224 {
Jamie Madill437fa652016-05-03 15:13:24 -04004225 context->handleError(Error(GL_INVALID_OPERATION, "Buffer not mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004226 return false;
4227 }
4228
4229 return true;
4230}
4231
4232bool ValidateMapBufferRangeBase(Context *context,
4233 GLenum target,
4234 GLintptr offset,
4235 GLsizeiptr length,
4236 GLbitfield access)
4237{
4238 if (!ValidBufferTarget(context, target))
4239 {
Jamie Madill437fa652016-05-03 15:13:24 -04004240 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004241 return false;
4242 }
4243
4244 if (offset < 0 || length < 0)
4245 {
Jamie Madill437fa652016-05-03 15:13:24 -04004246 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset or length."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004247 return false;
4248 }
4249
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004250 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004251
4252 if (!buffer)
4253 {
Jamie Madill437fa652016-05-03 15:13:24 -04004254 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to map buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004255 return false;
4256 }
4257
4258 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004259 CheckedNumeric<size_t> checkedOffset(offset);
4260 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004261
Jamie Madille2e406c2016-06-02 13:04:10 -04004262 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004263 {
Jamie Madill437fa652016-05-03 15:13:24 -04004264 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004265 Error(GL_INVALID_VALUE, "Mapped range does not fit into buffer dimensions."));
4266 return false;
4267 }
4268
4269 // Check for invalid bits in the mask
4270 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
4271 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
4272 GL_MAP_UNSYNCHRONIZED_BIT;
4273
4274 if (access & ~(allAccessBits))
4275 {
Jamie Madill437fa652016-05-03 15:13:24 -04004276 context->handleError(Error(GL_INVALID_VALUE, "Invalid access bits: 0x%X.", access));
Olli Etuaho4f667482016-03-30 15:56:35 +03004277 return false;
4278 }
4279
4280 if (length == 0)
4281 {
Jamie Madill437fa652016-05-03 15:13:24 -04004282 context->handleError(Error(GL_INVALID_OPERATION, "Buffer mapping length is zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004283 return false;
4284 }
4285
4286 if (buffer->isMapped())
4287 {
Jamie Madill437fa652016-05-03 15:13:24 -04004288 context->handleError(Error(GL_INVALID_OPERATION, "Buffer is already mapped."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004289 return false;
4290 }
4291
4292 // Check for invalid bit combinations
4293 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
4294 {
Jamie Madill437fa652016-05-03 15:13:24 -04004295 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004296 Error(GL_INVALID_OPERATION, "Need to map buffer for either reading or writing."));
4297 return false;
4298 }
4299
4300 GLbitfield writeOnlyBits =
4301 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
4302
4303 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
4304 {
Jamie Madill437fa652016-05-03 15:13:24 -04004305 context->handleError(Error(GL_INVALID_OPERATION,
Olli Etuaho4f667482016-03-30 15:56:35 +03004306 "Invalid access bits when mapping buffer for reading: 0x%X.",
4307 access));
4308 return false;
4309 }
4310
4311 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
4312 {
Jamie Madill437fa652016-05-03 15:13:24 -04004313 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004314 GL_INVALID_OPERATION,
4315 "The explicit flushing bit may only be set if the buffer is mapped for writing."));
4316 return false;
4317 }
4318 return true;
4319}
4320
4321bool ValidateFlushMappedBufferRangeBase(Context *context,
4322 GLenum target,
4323 GLintptr offset,
4324 GLsizeiptr length)
4325{
4326 if (offset < 0 || length < 0)
4327 {
Jamie Madill437fa652016-05-03 15:13:24 -04004328 context->handleError(Error(GL_INVALID_VALUE, "Invalid offset/length parameters."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004329 return false;
4330 }
4331
4332 if (!ValidBufferTarget(context, target))
4333 {
Jamie Madill437fa652016-05-03 15:13:24 -04004334 context->handleError(Error(GL_INVALID_ENUM, "Invalid buffer target."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004335 return false;
4336 }
4337
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004338 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004339
4340 if (buffer == nullptr)
4341 {
Jamie Madill437fa652016-05-03 15:13:24 -04004342 context->handleError(Error(GL_INVALID_OPERATION, "Attempted to flush buffer object zero."));
Olli Etuaho4f667482016-03-30 15:56:35 +03004343 return false;
4344 }
4345
4346 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4347 {
Jamie Madill437fa652016-05-03 15:13:24 -04004348 context->handleError(Error(
Olli Etuaho4f667482016-03-30 15:56:35 +03004349 GL_INVALID_OPERATION, "Attempted to flush a buffer not mapped for explicit flushing."));
4350 return false;
4351 }
4352
4353 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004354 CheckedNumeric<size_t> checkedOffset(offset);
4355 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004356
Jamie Madille2e406c2016-06-02 13:04:10 -04004357 if (!checkedSize.IsValid() ||
4358 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004359 {
Jamie Madill437fa652016-05-03 15:13:24 -04004360 context->handleError(
Olli Etuaho4f667482016-03-30 15:56:35 +03004361 Error(GL_INVALID_VALUE, "Flushed range does not fit into buffer mapping dimensions."));
4362 return false;
4363 }
4364
4365 return true;
4366}
4367
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004368bool ValidateGenerateMipmap(Context *context, GLenum target)
4369{
4370 if (!ValidTextureTarget(context, target))
4371 {
4372 context->handleError(Error(GL_INVALID_ENUM));
4373 return false;
4374 }
4375
4376 Texture *texture = context->getTargetTexture(target);
4377
4378 if (texture == nullptr)
4379 {
4380 context->handleError(Error(GL_INVALID_OPERATION));
4381 return false;
4382 }
4383
4384 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
4385
4386 // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
4387 // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
4388 if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
4389 {
4390 context->handleError(Error(GL_INVALID_OPERATION));
4391 return false;
4392 }
4393
Jamie Madilla3944d42016-07-22 22:13:26 -04004394 GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
4395 const auto &format = texture->getFormat(baseTarget, effectiveBaseLevel);
4396 const TextureCaps &formatCaps = context->getTextureCaps().get(format.asSized());
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004397
4398 // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
4399 // unsized formats or that are color renderable and filterable. Since we do not track if
4400 // the texture was created with sized or unsized format (only sized formats are stored),
4401 // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
4402 // be able to) because they aren't color renderable. Simply do a special case for LUMA
4403 // textures since they're the only texture format that can be created with unsized formats
4404 // that is not color renderable. New unsized formats are unlikely to be added, since ES2
4405 // was the last version to use add them.
Jamie Madilla3944d42016-07-22 22:13:26 -04004406 if (format.info->depthBits > 0 || format.info->stencilBits > 0 || !formatCaps.filterable ||
4407 (!formatCaps.renderable && !format.info->isLUMA()) || format.info->compressed)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004408 {
4409 context->handleError(Error(GL_INVALID_OPERATION));
4410 return false;
4411 }
4412
4413 // GL_EXT_sRGB does not support mipmap generation on sRGB textures
Jamie Madilla3944d42016-07-22 22:13:26 -04004414 if (context->getClientMajorVersion() == 2 && format.info->colorEncoding == GL_SRGB)
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004415 {
4416 context->handleError(Error(GL_INVALID_OPERATION));
4417 return false;
4418 }
4419
4420 // Non-power of 2 ES2 check
Geoff Lang55482a12016-11-21 16:54:01 -05004421 if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004422 (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
4423 !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
4424 {
Geoff Lang55482a12016-11-21 16:54:01 -05004425 ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
Olli Etuaho0f2b1562016-05-13 16:15:35 +03004426 context->handleError(Error(GL_INVALID_OPERATION));
4427 return false;
4428 }
4429
4430 // Cube completeness check
4431 if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
4432 {
4433 context->handleError(Error(GL_INVALID_OPERATION));
4434 return false;
4435 }
4436
4437 return true;
4438}
4439
Olli Etuaho41997e72016-03-10 13:38:39 +02004440bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
4441{
4442 return ValidateGenOrDelete(context, n);
4443}
4444
4445bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
4446{
4447 return ValidateGenOrDelete(context, n);
4448}
4449
4450bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
4451{
4452 return ValidateGenOrDelete(context, n);
4453}
4454
4455bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
4456{
4457 return ValidateGenOrDelete(context, n);
4458}
4459
4460bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
4461{
4462 return ValidateGenOrDelete(context, n);
4463}
4464
4465bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
4466{
4467 return ValidateGenOrDelete(context, n);
4468}
4469
4470bool ValidateGenTextures(Context *context, GLint n, GLuint *)
4471{
4472 return ValidateGenOrDelete(context, n);
4473}
4474
4475bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
4476{
4477 return ValidateGenOrDelete(context, n);
4478}
4479
4480bool ValidateGenOrDelete(Context *context, GLint n)
4481{
4482 if (n < 0)
4483 {
Jamie Madill437fa652016-05-03 15:13:24 -04004484 context->handleError(Error(GL_INVALID_VALUE, "n < 0"));
Olli Etuaho41997e72016-03-10 13:38:39 +02004485 return false;
4486 }
4487 return true;
4488}
4489
Geoff Langf41a7152016-09-19 15:11:17 -04004490bool ValidateEnable(Context *context, GLenum cap)
4491{
4492 if (!ValidCap(context, cap, false))
4493 {
4494 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4495 return false;
4496 }
4497
4498 if (context->getLimitations().noSampleAlphaToCoverageSupport &&
4499 cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
4500 {
4501 const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
4502 context->handleError(Error(GL_INVALID_OPERATION, errorMessage));
4503
4504 // We also output an error message to the debugger window if tracing is active, so that
4505 // developers can see the error message.
4506 ERR("%s", errorMessage);
Geoff Langf41a7152016-09-19 15:11:17 -04004507 return false;
4508 }
4509
4510 return true;
4511}
4512
4513bool ValidateDisable(Context *context, GLenum cap)
4514{
4515 if (!ValidCap(context, cap, false))
4516 {
4517 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4518 return false;
4519 }
4520
4521 return true;
4522}
4523
4524bool ValidateIsEnabled(Context *context, GLenum cap)
4525{
4526 if (!ValidCap(context, cap, true))
4527 {
4528 context->handleError(Error(GL_INVALID_ENUM, "Invalid cap."));
4529 return false;
4530 }
4531
4532 return true;
4533}
4534
Geoff Langff5b2d52016-09-07 11:32:23 -04004535bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4536{
4537 if (!context->getExtensions().robustClientMemory)
4538 {
4539 context->handleError(
4540 Error(GL_INVALID_OPERATION, "GL_ANGLE_robust_client_memory is not available."));
4541 return false;
4542 }
4543
4544 if (bufSize < 0)
4545 {
4546 context->handleError(Error(GL_INVALID_VALUE, "bufSize cannot be negative."));
4547 return false;
4548 }
4549
4550 return true;
4551}
4552
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004553bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4554{
4555 if (bufSize < numParams)
4556 {
4557 context->handleError(Error(GL_INVALID_OPERATION,
4558 "%u parameters are required but %i were provided.", numParams,
4559 bufSize));
4560 return false;
4561 }
4562
4563 return true;
4564}
4565
Geoff Langff5b2d52016-09-07 11:32:23 -04004566bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
4567 GLenum target,
4568 GLenum attachment,
4569 GLenum pname,
4570 GLsizei *numParams)
4571{
4572 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
4573 *numParams = 1;
4574
4575 if (!ValidFramebufferTarget(target))
4576 {
4577 context->handleError(Error(GL_INVALID_ENUM));
4578 return false;
4579 }
4580
4581 int clientVersion = context->getClientMajorVersion();
4582
4583 switch (pname)
4584 {
4585 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4586 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4587 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4588 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4589 break;
4590
4591 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4592 if (clientVersion < 3 && !context->getExtensions().sRGB)
4593 {
4594 context->handleError(Error(GL_INVALID_ENUM));
4595 return false;
4596 }
4597 break;
4598
4599 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4600 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4601 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4602 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4603 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4604 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4605 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4606 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4607 if (clientVersion < 3)
4608 {
4609 context->handleError(Error(GL_INVALID_ENUM));
4610 return false;
4611 }
4612 break;
4613
4614 default:
4615 context->handleError(Error(GL_INVALID_ENUM));
4616 return false;
4617 }
4618
4619 // Determine if the attachment is a valid enum
4620 switch (attachment)
4621 {
4622 case GL_BACK:
4623 case GL_FRONT:
4624 case GL_DEPTH:
4625 case GL_STENCIL:
4626 case GL_DEPTH_STENCIL_ATTACHMENT:
4627 if (clientVersion < 3)
4628 {
4629 context->handleError(Error(GL_INVALID_ENUM));
4630 return false;
4631 }
4632 break;
4633
4634 case GL_DEPTH_ATTACHMENT:
4635 case GL_STENCIL_ATTACHMENT:
4636 break;
4637
4638 default:
4639 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4640 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4641 {
4642 context->handleError(Error(GL_INVALID_ENUM));
4643 return false;
4644 }
4645 break;
4646 }
4647
4648 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4649 ASSERT(framebuffer);
4650
4651 if (framebuffer->id() == 0)
4652 {
4653 if (clientVersion < 3)
4654 {
4655 context->handleError(Error(GL_INVALID_OPERATION));
4656 return false;
4657 }
4658
4659 switch (attachment)
4660 {
4661 case GL_BACK:
4662 case GL_DEPTH:
4663 case GL_STENCIL:
4664 break;
4665
4666 default:
4667 context->handleError(Error(GL_INVALID_OPERATION));
4668 return false;
4669 }
4670 }
4671 else
4672 {
4673 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4674 {
4675 // Valid attachment query
4676 }
4677 else
4678 {
4679 switch (attachment)
4680 {
4681 case GL_DEPTH_ATTACHMENT:
4682 case GL_STENCIL_ATTACHMENT:
4683 break;
4684
4685 case GL_DEPTH_STENCIL_ATTACHMENT:
4686 if (!framebuffer->hasValidDepthStencil())
4687 {
4688 context->handleError(Error(GL_INVALID_OPERATION));
4689 return false;
4690 }
4691 break;
4692
4693 default:
4694 context->handleError(Error(GL_INVALID_OPERATION));
4695 return false;
4696 }
4697 }
4698 }
4699
4700 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4701 if (attachmentObject)
4702 {
4703 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4704 attachmentObject->type() == GL_TEXTURE ||
4705 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4706
4707 switch (pname)
4708 {
4709 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4710 if (attachmentObject->type() != GL_RENDERBUFFER &&
4711 attachmentObject->type() != GL_TEXTURE)
4712 {
4713 context->handleError(Error(GL_INVALID_ENUM));
4714 return false;
4715 }
4716 break;
4717
4718 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4719 if (attachmentObject->type() != GL_TEXTURE)
4720 {
4721 context->handleError(Error(GL_INVALID_ENUM));
4722 return false;
4723 }
4724 break;
4725
4726 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4727 if (attachmentObject->type() != GL_TEXTURE)
4728 {
4729 context->handleError(Error(GL_INVALID_ENUM));
4730 return false;
4731 }
4732 break;
4733
4734 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4735 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4736 {
4737 context->handleError(Error(GL_INVALID_OPERATION));
4738 return false;
4739 }
4740 break;
4741
4742 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4743 if (attachmentObject->type() != GL_TEXTURE)
4744 {
4745 context->handleError(Error(GL_INVALID_ENUM));
4746 return false;
4747 }
4748 break;
4749
4750 default:
4751 break;
4752 }
4753 }
4754 else
4755 {
4756 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4757 // is NONE, then querying any other pname will generate INVALID_ENUM.
4758
4759 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4760 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4761 // INVALID_OPERATION for all other pnames
4762
4763 switch (pname)
4764 {
4765 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4766 break;
4767
4768 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4769 if (clientVersion < 3)
4770 {
4771 context->handleError(Error(GL_INVALID_ENUM));
4772 return false;
4773 }
4774 break;
4775
4776 default:
4777 if (clientVersion < 3)
4778 {
4779 context->handleError(Error(GL_INVALID_ENUM));
4780 return false;
4781 }
4782 else
4783 {
4784 context->handleError(Error(GL_INVALID_OPERATION));
4785 return false;
4786 }
4787 }
4788 }
4789
4790 return true;
4791}
4792
4793bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4794 GLenum target,
4795 GLenum attachment,
4796 GLenum pname,
4797 GLsizei bufSize,
4798 GLsizei *numParams)
4799{
4800 if (!ValidateRobustEntryPoint(context, bufSize))
4801 {
4802 return false;
4803 }
4804
4805 if (!ValidateGetFramebufferAttachmentParameteriv(context, target, attachment, pname, numParams))
4806 {
4807 return false;
4808 }
4809
4810 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4811 {
4812 return false;
4813 }
4814
4815 return true;
4816}
4817
4818bool ValidateGetBufferParameteriv(ValidationContext *context,
4819 GLenum target,
4820 GLenum pname,
Geoff Langebebe1c2016-10-14 12:01:31 -04004821 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004822{
Geoff Langebebe1c2016-10-14 12:01:31 -04004823 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
Geoff Langff5b2d52016-09-07 11:32:23 -04004824}
4825
4826bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4827 GLenum target,
4828 GLenum pname,
4829 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004830 GLsizei *length,
4831 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004832{
4833 if (!ValidateRobustEntryPoint(context, bufSize))
4834 {
4835 return false;
4836 }
4837
Geoff Langebebe1c2016-10-14 12:01:31 -04004838 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004839 {
4840 return false;
4841 }
4842
Geoff Langebebe1c2016-10-14 12:01:31 -04004843 if (!ValidateRobustBufferSize(context, bufSize, *length))
4844 {
4845 return false;
4846 }
4847
4848 return true;
4849}
4850
4851bool ValidateGetBufferParameteri64v(ValidationContext *context,
4852 GLenum target,
4853 GLenum pname,
4854 GLint64 *params)
4855{
4856 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4857}
4858
4859bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4860 GLenum target,
4861 GLenum pname,
4862 GLsizei bufSize,
4863 GLsizei *length,
4864 GLint64 *params)
4865{
4866 if (!ValidateRobustEntryPoint(context, bufSize))
4867 {
4868 return false;
4869 }
4870
4871 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4872 {
4873 return false;
4874 }
4875
4876 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004877 {
4878 return false;
4879 }
4880
4881 return true;
4882}
4883
4884bool ValidateGetProgramiv(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
4885{
4886 // Currently, all GetProgramiv queries return 1 parameter
4887 *numParams = 1;
4888
4889 Program *programObject = GetValidProgram(context, program);
4890 if (!programObject)
4891 {
4892 return false;
4893 }
4894
4895 switch (pname)
4896 {
4897 case GL_DELETE_STATUS:
4898 case GL_LINK_STATUS:
4899 case GL_VALIDATE_STATUS:
4900 case GL_INFO_LOG_LENGTH:
4901 case GL_ATTACHED_SHADERS:
4902 case GL_ACTIVE_ATTRIBUTES:
4903 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4904 case GL_ACTIVE_UNIFORMS:
4905 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4906 break;
4907
4908 case GL_PROGRAM_BINARY_LENGTH:
4909 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4910 {
4911 context->handleError(Error(GL_INVALID_ENUM,
4912 "Querying GL_PROGRAM_BINARY_LENGTH requires "
4913 "GL_OES_get_program_binary or ES 3.0."));
4914 return false;
4915 }
4916 break;
4917
4918 case GL_ACTIVE_UNIFORM_BLOCKS:
4919 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4920 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4921 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4922 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4923 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4924 if (context->getClientMajorVersion() < 3)
4925 {
4926 context->handleError(Error(GL_INVALID_ENUM, "Querying requires at least ES 3.0."));
4927 return false;
4928 }
4929 break;
4930
4931 default:
4932 context->handleError(Error(GL_INVALID_ENUM, "Unknown parameter name."));
4933 return false;
4934 }
4935
4936 return true;
4937}
4938
4939bool ValidateGetProgramivRobustANGLE(Context *context,
4940 GLuint program,
4941 GLenum pname,
4942 GLsizei bufSize,
4943 GLsizei *numParams)
4944{
4945 if (!ValidateRobustEntryPoint(context, bufSize))
4946 {
4947 return false;
4948 }
4949
4950 if (!ValidateGetProgramiv(context, program, pname, numParams))
4951 {
4952 return false;
4953 }
4954
4955 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4956 {
4957 return false;
4958 }
4959
4960 return true;
4961}
4962
Geoff Lang740d9022016-10-07 11:20:52 -04004963bool ValidateGetRenderbufferParameteriv(Context *context,
4964 GLenum target,
4965 GLenum pname,
4966 GLint *params)
4967{
4968 return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
4969}
4970
4971bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4972 GLenum target,
4973 GLenum pname,
4974 GLsizei bufSize,
4975 GLsizei *length,
4976 GLint *params)
4977{
4978 if (!ValidateRobustEntryPoint(context, bufSize))
4979 {
4980 return false;
4981 }
4982
4983 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4984 {
4985 return false;
4986 }
4987
4988 if (!ValidateRobustBufferSize(context, bufSize, *length))
4989 {
4990 return false;
4991 }
4992
4993 return true;
4994}
4995
Geoff Langd7d0ed32016-10-07 11:33:51 -04004996bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
4997{
4998 return ValidateGetShaderivBase(context, shader, pname, nullptr);
4999}
5000
5001bool ValidateGetShaderivRobustANGLE(Context *context,
5002 GLuint shader,
5003 GLenum pname,
5004 GLsizei bufSize,
5005 GLsizei *length,
5006 GLint *params)
5007{
5008 if (!ValidateRobustEntryPoint(context, bufSize))
5009 {
5010 return false;
5011 }
5012
5013 if (!ValidateGetShaderivBase(context, shader, pname, length))
5014 {
5015 return false;
5016 }
5017
5018 if (!ValidateRobustBufferSize(context, bufSize, *length))
5019 {
5020 return false;
5021 }
5022
5023 return true;
5024}
5025
Geoff Langc1984ed2016-10-07 12:41:00 -04005026bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
5027{
5028 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5029}
5030
5031bool ValidateGetTexParameterfvRobustANGLE(Context *context,
5032 GLenum target,
5033 GLenum pname,
5034 GLsizei bufSize,
5035 GLsizei *length,
5036 GLfloat *params)
5037{
5038 if (!ValidateRobustEntryPoint(context, bufSize))
5039 {
5040 return false;
5041 }
5042
5043 if (!ValidateGetTexParameterBase(context, target, pname, length))
5044 {
5045 return false;
5046 }
5047
5048 if (!ValidateRobustBufferSize(context, bufSize, *length))
5049 {
5050 return false;
5051 }
5052
5053 return true;
5054}
5055
5056bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
5057{
5058 return ValidateGetTexParameterBase(context, target, pname, nullptr);
5059}
5060
5061bool ValidateGetTexParameterivRobustANGLE(Context *context,
5062 GLenum target,
5063 GLenum pname,
5064 GLsizei bufSize,
5065 GLsizei *length,
5066 GLint *params)
5067{
5068 if (!ValidateRobustEntryPoint(context, bufSize))
5069 {
5070 return false;
5071 }
5072
5073 if (!ValidateGetTexParameterBase(context, target, pname, length))
5074 {
5075 return false;
5076 }
5077
5078 if (!ValidateRobustBufferSize(context, bufSize, *length))
5079 {
5080 return false;
5081 }
5082
5083 return true;
5084}
5085
5086bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
5087{
5088 return ValidateTexParameterBase(context, target, pname, -1, &param);
5089}
5090
5091bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
5092{
5093 return ValidateTexParameterBase(context, target, pname, -1, params);
5094}
5095
5096bool ValidateTexParameterfvRobustANGLE(Context *context,
5097 GLenum target,
5098 GLenum pname,
5099 GLsizei bufSize,
5100 const GLfloat *params)
5101{
5102 if (!ValidateRobustEntryPoint(context, bufSize))
5103 {
5104 return false;
5105 }
5106
5107 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5108}
5109
5110bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
5111{
5112 return ValidateTexParameterBase(context, target, pname, -1, &param);
5113}
5114
5115bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
5116{
5117 return ValidateTexParameterBase(context, target, pname, -1, params);
5118}
5119
5120bool ValidateTexParameterivRobustANGLE(Context *context,
5121 GLenum target,
5122 GLenum pname,
5123 GLsizei bufSize,
5124 const GLint *params)
5125{
5126 if (!ValidateRobustEntryPoint(context, bufSize))
5127 {
5128 return false;
5129 }
5130
5131 return ValidateTexParameterBase(context, target, pname, bufSize, params);
5132}
5133
5134bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
5135{
5136 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5137}
5138
5139bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
5140 GLuint sampler,
5141 GLenum pname,
5142 GLuint bufSize,
5143 GLsizei *length,
5144 GLfloat *params)
5145{
5146 if (!ValidateRobustEntryPoint(context, bufSize))
5147 {
5148 return false;
5149 }
5150
5151 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5152 {
5153 return false;
5154 }
5155
5156 if (!ValidateRobustBufferSize(context, bufSize, *length))
5157 {
5158 return false;
5159 }
5160
5161 return true;
5162}
5163
5164bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
5165{
5166 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
5167}
5168
5169bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
5170 GLuint sampler,
5171 GLenum pname,
5172 GLuint bufSize,
5173 GLsizei *length,
5174 GLint *params)
5175{
5176 if (!ValidateRobustEntryPoint(context, bufSize))
5177 {
5178 return false;
5179 }
5180
5181 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
5182 {
5183 return false;
5184 }
5185
5186 if (!ValidateRobustBufferSize(context, bufSize, *length))
5187 {
5188 return false;
5189 }
5190
5191 return true;
5192}
5193
5194bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
5195{
5196 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5197}
5198
5199bool ValidateSamplerParameterfv(Context *context,
5200 GLuint sampler,
5201 GLenum pname,
5202 const GLfloat *params)
5203{
5204 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5205}
5206
5207bool ValidateSamplerParameterfvRobustANGLE(Context *context,
5208 GLuint sampler,
5209 GLenum pname,
5210 GLsizei bufSize,
5211 const GLfloat *params)
5212{
5213 if (!ValidateRobustEntryPoint(context, bufSize))
5214 {
5215 return false;
5216 }
5217
5218 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5219}
5220
5221bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
5222{
5223 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
5224}
5225
5226bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
5227{
5228 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
5229}
5230
5231bool ValidateSamplerParameterivRobustANGLE(Context *context,
5232 GLuint sampler,
5233 GLenum pname,
5234 GLsizei bufSize,
5235 const GLint *params)
5236{
5237 if (!ValidateRobustEntryPoint(context, bufSize))
5238 {
5239 return false;
5240 }
5241
5242 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
5243}
5244
Geoff Lang0b031062016-10-13 14:30:04 -04005245bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
5246{
5247 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5248}
5249
5250bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
5251 GLuint index,
5252 GLenum pname,
5253 GLsizei bufSize,
5254 GLsizei *length,
5255 GLfloat *params)
5256{
5257 if (!ValidateRobustEntryPoint(context, bufSize))
5258 {
5259 return false;
5260 }
5261
5262 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5263 {
5264 return false;
5265 }
5266
5267 if (!ValidateRobustBufferSize(context, bufSize, *length))
5268 {
5269 return false;
5270 }
5271
5272 return true;
5273}
5274
5275bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
5276{
5277 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
5278}
5279
5280bool ValidateGetVertexAttribivRobustANGLE(Context *context,
5281 GLuint index,
5282 GLenum pname,
5283 GLsizei bufSize,
5284 GLsizei *length,
5285 GLint *params)
5286{
5287 if (!ValidateRobustEntryPoint(context, bufSize))
5288 {
5289 return false;
5290 }
5291
5292 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
5293 {
5294 return false;
5295 }
5296
5297 if (!ValidateRobustBufferSize(context, bufSize, *length))
5298 {
5299 return false;
5300 }
5301
5302 return true;
5303}
5304
5305bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
5306{
5307 return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
5308}
5309
5310bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
5311 GLuint index,
5312 GLenum pname,
5313 GLsizei bufSize,
5314 GLsizei *length,
5315 void **pointer)
5316{
5317 if (!ValidateRobustEntryPoint(context, bufSize))
5318 {
5319 return false;
5320 }
5321
5322 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
5323 {
5324 return false;
5325 }
5326
5327 if (!ValidateRobustBufferSize(context, bufSize, *length))
5328 {
5329 return false;
5330 }
5331
5332 return true;
5333}
5334
5335bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
5336{
5337 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5338}
5339
5340bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
5341 GLuint index,
5342 GLenum pname,
5343 GLsizei bufSize,
5344 GLsizei *length,
5345 GLint *params)
5346{
5347 if (!ValidateRobustEntryPoint(context, bufSize))
5348 {
5349 return false;
5350 }
5351
5352 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5353 {
5354 return false;
5355 }
5356
5357 if (!ValidateRobustBufferSize(context, bufSize, *length))
5358 {
5359 return false;
5360 }
5361
5362 return true;
5363}
5364
5365bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
5366{
5367 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
5368}
5369
5370bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5371 GLuint index,
5372 GLenum pname,
5373 GLsizei bufSize,
5374 GLsizei *length,
5375 GLuint *params)
5376{
5377 if (!ValidateRobustEntryPoint(context, bufSize))
5378 {
5379 return false;
5380 }
5381
5382 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
5383 {
5384 return false;
5385 }
5386
5387 if (!ValidateRobustBufferSize(context, bufSize, *length))
5388 {
5389 return false;
5390 }
5391
5392 return true;
5393}
5394
Geoff Lang6899b872016-10-14 11:30:13 -04005395bool ValidateGetActiveUniformBlockiv(Context *context,
5396 GLuint program,
5397 GLuint uniformBlockIndex,
5398 GLenum pname,
5399 GLint *params)
5400{
5401 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
5402}
5403
5404bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5405 GLuint program,
5406 GLuint uniformBlockIndex,
5407 GLenum pname,
5408 GLsizei bufSize,
5409 GLsizei *length,
5410 GLint *params)
5411{
5412 if (!ValidateRobustEntryPoint(context, bufSize))
5413 {
5414 return false;
5415 }
5416
5417 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
5418 {
5419 return false;
5420 }
5421
5422 if (!ValidateRobustBufferSize(context, bufSize, *length))
5423 {
5424 return false;
5425 }
5426
5427 return true;
5428}
5429
Geoff Lang0a9661f2016-10-20 10:59:20 -07005430bool ValidateGetInternalFormativ(Context *context,
5431 GLenum target,
5432 GLenum internalformat,
5433 GLenum pname,
5434 GLsizei bufSize,
5435 GLint *params)
5436{
5437 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5438 nullptr);
5439}
5440
5441bool ValidateGetInternalFormativRobustANGLE(Context *context,
5442 GLenum target,
5443 GLenum internalformat,
5444 GLenum pname,
5445 GLsizei bufSize,
5446 GLsizei *length,
5447 GLint *params)
5448{
5449 if (!ValidateRobustEntryPoint(context, bufSize))
5450 {
5451 return false;
5452 }
5453
5454 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
5455 {
5456 return false;
5457 }
5458
5459 if (!ValidateRobustBufferSize(context, bufSize, *length))
5460 {
5461 return false;
5462 }
5463
5464 return true;
5465}
5466
Jamie Madillc29968b2016-01-20 11:17:23 -05005467} // namespace gl